Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom the right click menu of elfinder (a jquery file manager plugin)

I am working on a customized share button with the elfinder, there is tutorial about how to custom the right click menu, and I have implemented it. However, there are some rules I would like to apply for the menu

1) For folder only,  exclude the button for file
2) For root level only, exclude the button for sub level folder 
3) For single folder only, if select more than one folder will exclude the button

Here is the current code, right now have the share button but not with the above rules:

    elFinder.prototype.i18.zh_TW.messages['cmdsharefolder'] = 'Share';
    elFinder.prototype._options.commands.push('sharefolder');
    elFinder.prototype.commands.sharefolder = function () {
        this.exec = function (hashes) {
            //open share menu
        }
        this.getstate = function () {
            return 0; 
        }
    }

And the elfinder instance:

var elfinder = $('#elfinder').elfinder({
    url: '<?= $connector; ?>',
    soundPath: '<?= site_url('assets/plugins/elFinder/sounds/rm.wav'); ?>',
    height: 700,
    lang: 'zh_TW',
    uiOptions: {
        // toolbar configuration
        toolbar: [
            ['back', 'forward'],
            ['reload'],
            ['mkdir', 'upload'],
            ['copy', 'cut', 'paste', 'rm'],
            ['rename'],
            ['view', 'sort']
        ]
    },
    contextmenu: {
        navbar: ['open', '|', 'copy', 'cut', 'paste', 'duplicate', '|', 'rm', '|', 'info'],
        cwd: ['reload', 'back', '|', 'upload', 'mkdir', 'paste', '|', 'info'],
        files: [
            'open', 'quicklook', 'sharefolder', '|', 'download', '|', 'copy', 'cut', 'paste', 'rm', '|', 'rename', '|', 'info'
        ]
    },
    ui: ['toolbar', 'tree', 'stat']
}).elfinder('instance');

The problems are :

1) how to apply the rules above? (if the rules can not apply, can workaround with checking and popup alert box, please suggest the way for checking, thanks)

2) are there any way to capture which folder is selected e.g. full folder path etc...

Here is the doc I have studied , the sample case is for general use: https://github.com/Studio-42/elFinder/wiki/Custom-context-menu-command

Thanks a lot for helping.

like image 866
user782104 Avatar asked May 19 '16 05:05

user782104


1 Answers

What you're trying to accomplish is possible, but it highly depends on how your connector works.

In order to work with your rules, you either have to add code in this.exec or this.getstate. There are pros and cons for each option.

  1. If you add the code to this.getstate your code might be executed more than once for a single action (example: when you select multiple folders, the function is executed when you click on the first folder, on the last and when you right click).

    However, using this.getstate you're able to hide the option (button) on any situation that doesn't meet the requirements (rules).

  2. Adding code to this.exec assures the code is only executed once per action, but the button is always present even if the rules don't apply.

    If you choose this, you'll need to work with some kind of alert or dialog messages to the user, to inform them why the share menu isn't displayed.

In the following code, I've used this.getstate, but you can move the code to this.exec. On the Javascript side you need to use something like this:

elFinder.prototype.i18.zh_TW.messages['cmdsharefolder'] = 'Share';
elFinder.prototype._options.commands.push('sharefolder');
elFinder.prototype.commands.sharefolder = function () {
    var self  = this,
        fm    = self.fm;

    this.exec = function (hashes) {
        // Display the share menu
    };

    this.getstate = function () {
        var hashes = self.fm.selected(), result = 0;
        // Verifies rule nr 3: For single folder only,
        //  if select more than one folder will exclude the button
        if (hashes.length > 1) {
            return -1;
        }

        // Rule 1 and 2 exclude itself. By this I mean that rule nr 2
        // takes precedence over rule nr 1, so you just need to check
        // if the selected hash is a root folder.
        $.ajax({
            url: 'file-manager/check-rule-on-hash',
            data: hashes,
            type: 'get',
            async: false,
            dataType: 'json',
            success: function(response) {
                if (!response.isRoot) {
                    result = -1;
                }
            }
        });

        return result;
    }
}

Explanation:

  1. Rule nr 3 is easy, because you have access to the number of selected items through Javascript. So you just need to count the number of selected hashes. If that number is greater than 1, that means the user selected more than one item and the menu shouldn't be displayed.

  2. Rule nr 2 is a little trickier, because you need to "validate" the selected hash, and this is why I started to say that this depends on how your connector works.

    For instance, I have a custom PHP connector, where the folder structure is defined through a database table. Although all files are physically stored on the hard drive, the meta data is stored on the same table (mostly because all permissions are defined via database). In my case it's somewhat easy to perform an ajax call and check if a given hash is a root folder, because that info is stored on the database and I can retrieve that info with a simple query.

Since I can't be sure on how your connector works, the generic solution is to perform an ajax call to the server, with the selected hash, and verify if that hash is a root folder. The server should return an object with the property isRoot that's either true or false.

like image 122
Luís Cruz Avatar answered Oct 20 '22 16:10

Luís Cruz