javascript - ExtJS 4 Grid 自定义列排序(文件管理器样式)

标签 javascript extjs extjs4

我正准备使用 ExtJS 4 制作一个基本的文件管理器。我现在面临的问题是:如何为 grid panel 进行自定义排序单击列时

假设我们有商店字段:

[
    { name: "is_dir", type: "boolean" },
    { name: "name",   type: "string"  },
    { name: "size",   type: "int"     }
]

以及来自数组的数据:

[
    { is_dir: true,  name: "..",        size: 0    },
    { is_dir: false, name: "file2.txt", size: 512  },
    { is_dir: true,  name: "folder2",   size: 0    },
    { is_dir: false, name: "file3.txt", size: 1024 },
    { is_dir: true,  name: "folder1",   size: 0    },
    { is_dir: true,  name: "file1.txt", size: 1024 },
    // ...
]

想法是像在任何文件管理器中一样进行排序(例如 Total CommanderMCFAR 等),因此:

  • 名称为“..”的项目总是放在顶部
  • 目录按排序顺序在“..”(如果存在)之后
  • 文件按排序顺序排在目录(如果存在)之后

例如,按名称和大小排序的输出应该是:

^ Name           | Size               Name             | ^ Size
-----------------------               -------------------------
..               | 0                  ..               | 0
folder1          | 0                  folder1          | 0
folder2          | 0                  folder2          | 0
file1.txt        | 1024               file2.txt        | 512
file2.txt        | 512                file1.txt        | 1024
file3.txt        | 1024               file3.txt        | 1024

我尝试为存储 sorters 属性编写自定义 sorterFn,但它没有帮助。我相信应该有一些简单的解决方案。

最佳答案

您可以重写商店的 sort 方法:

Ext.define('My.store.FileStore', {
    extend: 'Ext.data.Store',

    sort: function () {
        this.doSort(function() {
            // Custom sorting function
            console.log(arguments);
            return Math.random() > 0.5 ? 1 : -1; // :)
        });
    }
});

更新

Ext.define('FileModel', {
    extend: 'Ext.data.Model',
    fields: [
        { name: "is_dir", type: "boolean" },
        { name: "name",   type: "string"  },
        { name: "size",   type: "int"     }
    ]
});

Ext.define('FileStore', {
    extend: 'Ext.data.Store',
    model: 'FileModel',
    data: [
        { is_dir: true,  name: "..",        size: 0    },
        { is_dir: false, name: "file2.txt", size: 512  },
        { is_dir: true,  name: "folder2",   size: 0    },
        { is_dir: false, name: "file3.txt", size: 1024 },
        { is_dir: true,  name: "folder1",   size: 0    },
        { is_dir: false, name: "file1.txt", size: 1024 },
    ],

    sorters: [{
        property: 'name',
        direction: 'ASC'
    }],

    sort: function(params) {
        var dir = params ? params.direction : 'ASC';
        var prop = params ? params.property : 'name';

        this.callParent(arguments); // UPDATE 2                    

        this.doSort(function(rec1, rec2) {
            var rec1sort = '';
            var rec2sort = '';

            if (rec1.get('is_dir') && rec2.get('is_dir')) {
                // both dirs
                if (rec1.get('name') == '..') {
                    return -1;
                }
                else if (rec2.get('name') == '..') {
                    return 1;
                }
                else {
                    return rec1.get('name').localeCompare(rec2.get('name')) * (dir == 'ASC' ? 1 : -1);;
                }
            }
            else if (rec1.get('is_dir') != rec2.get('is_dir')) {
                // file and dir
                if (rec1.get('is_dir')) {
                    if (rec1.get('name') == '..') {
                        return -2;
                    }
                    else {
                        return -1;
                    }
                }
                else {
                    if (rec2.get('name') == '..') {
                        return 2;
                    }
                    else {
                        return 1;
                    }
                }
            }
            else if (!rec1.get('is_dir') && !rec2.get('is_dir')) {
                // both files
                var result;
                if (typeof rec1.get(prop) == 'number') {
                    result = rec1.get(prop) - rec2.get(prop);
                    if (result == 0) {
                        result = rec1.get('name').localeCompare(rec2.get('name'));
                    }
                }
                else {
                    result = rec1.get('name').localeCompare(rec2.get('name'));
                }
                return dir == 'ASC' ? result : result * -1;
            }
        });
    }
});    

var grid = Ext.create('Ext.grid.Panel', {
    title: 'Files',
    store: Ext.create('FileStore'),
    renderTo: Ext.getBody(),
    columns: [{
        header: 'Name',
        dataIndex: 'name'
    }, {
        header: 'Size',
        dataIndex: 'size'    
    }]
});

关于javascript - ExtJS 4 Grid 自定义列排序(文件管理器样式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12932007/

相关文章:

javascript - 根据另一个下拉列表的选定值生成下拉选项

javascript - 如何使用 ExtJs 将 Form 放入 TabPanel 中?

javascript - ExtJS - 堆积条形图

javascript - extjs,是否可以压缩加载ext-all.js?

javascript - extJS - 从同一 Controller 中的另一个函数调用一个函数

css - 无法在 Extjs 中为 chrome 动态应用背景面板图像

javascript - 是否可以使用 JavaScript 在 Firefox、Safari 和 Chrome 中读取剪贴板?

javascript - 如何在Jquery中多次调用一个函数来添加事件监听器而不是只监听最后一个?

javascript - 如何在 Backbone 模型中正确实现解析以包含集合?

javascript - 从不同按钮调用的独特弹出窗口 - ExtJS