`
sxu
  • 浏览: 38454 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Extjs TreeStore+pagingToolbar 分页

阅读更多

Extjs很强大,但也很庞大,还有一些地方不满足一些需求,变态需求就另说了。
       在4中Tree不带有分页,为了满足需求,只能扩展Ext的组件。
       仔细看TreeStore中源码,可以对比着Store中的源码,其实TreeStore中只是缺少了分页参数,以及对这些参数的逻辑和封装。我们只需要传入参数,加入分页逻辑,并封装起来。
       思路有了,就按着需求写。

 

 

 

 

/**

 * Extjs4.1 TreeStore 分页 

 * 

 * @作者:徐盛

 * @日期:2012-10-23

 * @用法:

 * Ext.create('APP.plugin.TreeStore', {

 * model: 'myModel',

 * storeId: 'MyTreeModel',

 * proxy: {

 * type: 'ajax',

 * url: 'url.do',

 * reader: {

 * type: 'json',

 * root: 'myTree',

 * totalProperty: 'totalProperty' // 一定需要这个参数接受后台返回的总条数 

 * }

 * },

 * root: {

 * id: 0,

 * text: 'root',

 * expanded: true

 * }

 * })

 *    

 *   其余都一样,主要是totalProperty,这个返回总条数

 *

 * @说明:

 * 目前只能实现root节点下的分页。

 *     在原Extjs4.1 TreeStore中加入的分页所需参数。

 * 如不满足需求,需自行调试加入方法。

 *      联系QQ:78264486

 *

 */

Ext.define('APP.plugin.TreeStore', {

extend: 'Ext.data.TreeStore',

alias: 'store.MyTreeStore',

/**

* 每页显示条数

*

*/

pageSize: undefined,

/**

* 当前页 默认为第一页

*

*/

currentPage: 1,

purgePageCount: 5,

defaultPageSize: 25,

/**

* 构造函数

*

*/

constructor: function(config) {

        var me = this,

            root,

            fields,

            defaultRoot,

data,

proxy;

 

        config = Ext.apply({}, config);

/**

         * @event prefetch

         * Fires whenever records have been prefetched

         * @param {Ext.data.Store} this

         * @param {Ext.data.Model[]} records An array of records.

         * @param {Boolean} successful True if the operation was successful.

         * @param {Ext.data.Operation} operation The associated operation

         */

        data = config.data || me.data;

 

        /**

         * @property {Ext.util.MixedCollection} data

         * The MixedCollection that holds this store's local cache of records.

         */

        me.data = new Ext.util.MixedCollection(false, Ext.data.Store.recordIdFn);

if (data) {

            me.inlineData = data;

            delete config.data;

        }

 

        /**

         * If we have no fields declare for the store, add some defaults.

         * These will be ignored if a model is explicitly specified.

         */

        fields = config.fields || me.fields;

        if (!fields) {

            config.fields = [

                {name: 'text', type: 'string'}

            ];

            defaultRoot = config.defaultRootProperty || me.defaultRootProperty;

            if (defaultRoot !== me.defaultRootProperty) {

                config.fields.push({

                    name: defaultRoot,   

                    type: 'auto',   

                    defaultValue: null, 

                    persist: false

                });

            }

        }

 

        me.callParent([config]);

/**

* @property {Ext.data.Store.PageMap} pageMap

* Internal PageMap instance.

* @private

*/

me.pageMap = new me.PageMap({

pageSize: me.pageSize,

maxSize: me.purgePageCount,

listeners: {

// Whenever PageMap gets cleared, it means we re no longer interested in 

// any outstanding page prefetches, so cancel tham all

clear: me.cancelAllPrefetches,

scope: me

}

});

me.pageRequests = {};

me.sortOnLoad = false;

me.filterOnLoad = false;

proxy = me.proxy;

        data = me.inlineData;

if (data) {

            if (proxy instanceof Ext.data.proxy.Memory) {

                proxy.data = data;

                me.read();

            } else {

                me.add.apply(me, [data]);

            }

 

            me.sort();

            delete me.inlineData;

        } else if (me.autoLoad) {

            Ext.defer(me.load, 10, me, [ typeof me.autoLoad === 'object' ? me.autoLoad : undefined ]);

            // Remove the defer call, we may need reinstate this at some point, but currently it's not obvious why it's here.

            // this.load(typeof this.autoLoad == 'object' ? this.autoLoad : undefined);

        }

        // We create our data tree.

        me.tree = new Ext.data.Tree();

 

        me.relayEvents(me.tree, [

            /**

             * @event append

             * @inheritdoc Ext.data.Tree#append

             */

            "append",

 

            /**

             * @event remove

             * @inheritdoc Ext.data.Tree#remove

             */

            "remove",

 

            /**

             * @event move

             * @inheritdoc Ext.data.Tree#move

             */

            "move",

 

            /**

             * @event insert

             * @inheritdoc Ext.data.Tree#insert

             */

            "insert",

 

            /**

             * @event beforeappend

             * @inheritdoc Ext.data.Tree#beforeappend

             */

            "beforeappend",

 

            /**

             * @event beforeremove

             * @inheritdoc Ext.data.Tree#beforeremove

             */

            "beforeremove",

 

            /**

             * @event beforemove

             * @inheritdoc Ext.data.Tree#beforemove

             */

            "beforemove",

 

            /**

             * @event beforeinsert

             * @inheritdoc Ext.data.Tree#beforeinsert

             */

            "beforeinsert",

 

            /**

             * @event expand

             * @inheritdoc Ext.data.Tree#expand

             */

            "expand",

 

            /**

             * @event collapse

             * @inheritdoc Ext.data.Tree#collapse

             */

            "collapse",

 

            /**

             * @event beforeexpand

             * @inheritdoc Ext.data.Tree#beforeexpand

             */

            "beforeexpand",

 

            /**

             * @event beforecollapse

             * @inheritdoc Ext.data.Tree#beforecollapse

             */

            "beforecollapse",

 

            /**

             * @event sort

             * @inheritdoc Ext.data.Tree#sort

             */

            "sort",

 

            /**

             * @event rootchange

             * @inheritdoc Ext.data.Tree#rootchange

             */

            "rootchange"

        ]);

 

        me.tree.on({

            scope: me,

            remove: me.onNodeRemove,

            // this event must follow the relay to beforeitemexpand to allow users to

            // cancel the expand:

            beforeexpand: me.onBeforeNodeExpand,

            beforecollapse: me.onBeforeNodeCollapse,

            append: me.onNodeAdded,

            insert: me.onNodeAdded,

            sort: me.onNodeSort

        });

 

        me.onBeforeSort();

 

        root = me.root;

        if (root) {

            delete me.root;

            me.setRootNode(root);

        }

 

        //<deprecated since=0.99>

        if (Ext.isDefined(me.nodeParameter)) {

            if (Ext.isDefined(Ext.global.console)) {

                Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');

            }

            me.nodeParam = me.nodeParameter;

            delete me.nodeParameter;

        }

        //</deprecated>

    },

/**

     * Loads the Store using its configured {@link #proxy}.

     * @param {Object} options (Optional) config object. This is passed into the {@link Ext.data.Operation Operation}

     * object that is created and then sent to the proxy's {@link Ext.data.proxy.Proxy#read} function.

     * The options can also contain a node, which indicates which node is to be loaded. If not specified, it will

     * default to the root node.

     */

    load: function(options) {

        options = options || {};

        options.params = options.params || {};

 

        var me = this,

            node = options.node || me.tree.getRootNode();

options.page = options.page || me.currentPage;

        options.start = (options.start !== undefined) ? options.start : (options.page - 1) * me.pageSize;

        options.limit = options.limit || me.pageSize;

 

        // If there is not a node it means the user hasnt defined a rootnode yet. In this case lets just

        // create one for them.

        if (!node) {

            node = me.setRootNode({

                expanded: true

            }, true);

        }

 

        // Assign the ID of the Operation so that a REST proxy can create the correct URL

        options.id = node.getId();

 

        if (me.clearOnLoad) {

            if(me.clearRemovedOnLoad) {

                // clear from the removed array any nodes that were descendants of the node being reloaded so that they do not get saved on next sync.

                me.clearRemoved(node);

            }

            // temporarily remove the onNodeRemove event listener so that when removeAll is called, the removed nodes do not get added to the removed array

            me.tree.un('remove', me.onNodeRemove, me);

            // remove all the nodes

            node.removeAll(false);

            // reattach the onNodeRemove listener

            me.tree.on('remove', me.onNodeRemove, me);

        }

 

        Ext.applyIf(options, {

            node: node

        });

        options.params[me.nodeParam] = node ? node.getId() : 'root';

 

        if (node) {

            node.set('loading', true);

        }

 

        return me.callParent([options]);

    },

// inherit docs

    onProxyLoad: function(operation) {

        var me = this,

            successful = operation.wasSuccessful(),

            records = operation.getRecords(),

            node = operation.node,

resultSet = operation.getResultSet();

if (resultSet) {

me.totalCount = resultSet.total;

}

me.mycount = resultSet.count;

 

        me.loading = false;

        node.set('loading', false);

        if (successful) {

            if (!me.clearOnLoad) {

                records = me.cleanRecords(node, records);

            }

            records = me.fillNode(node, records);

        }

        // The load event has an extra node parameter

        // (differing from the load event described in AbstractStore)

        /**

         * @event load

         * Fires whenever the store reads data from a remote data source.

         * @param {Ext.data.TreeStore} this

         * @param {Ext.data.NodeInterface} node The node that was loaded.

         * @param {Ext.data.Model[]} records An array of records.

         * @param {Boolean} successful True if the operation was successful.

         */

        // deprecate read?

        me.fireEvent('read', me, operation.node, records, successful);

        me.fireEvent('load', me, operation.node, records, successful);

        //this is a callback that would have been passed to the 'read' function and is optional

        Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);

    },

/**

* 获取总条数

*

*/

getTotalCount: function() {

        return this.totalCount || 0;

    },

/**

* 获取当前data中条目数

*

*/

getCount: function () {

return this.mycount || 0;

},

/**

     * Loads a given 'page' of data by setting the start and limit values appropriately. Internally this just causes a normal

     * load operation, passing in calculated 'start' and 'limit' params

     * @param {Number} page The number of the page to load

     * @param {Object} options See options for {@link #method-load}

     */

loadPage: function(page, options) {

        var me = this;

 

        me.currentPage = page;

 

        // Copy options into a new object so as not to mutate passed in objects

        options = Ext.apply({

            page: page,

            start: (page - 1) * me.pageSize,

            limit: me.pageSize,

            addRecords: !me.clearOnPageLoad

        }, options);

 

        if (me.buffered) {

            return me.loadToPrefetch(options);

        }

        me.read(options);

    },

/**

     * Loads the next 'page' in the current data set

     * @param {Object} options See options for {@link #method-load}

     */

    nextPage: function(options) {

        this.loadPage(this.currentPage + 1, options);

    },

 

    /**

     * Loads the previous 'page' in the current data set

     * @param {Object} options See options for {@link #method-load}

     */

    previousPage: function(options) {

        this.loadPage(this.currentPage - 1, options);

    },

/**

     * @private

     * Cancels all pending prefetch requests.

     *

     * This is called when the page map is cleared.

     *

     * Any requests which still make it through will be for the previous page map generation

     * (generation is incremented upon clear), and so will be rejected upon arrival.

     */

    cancelAllPrefetches: function() {

        var me = this,

            reqs = me.pageRequests,

            req,

            page;

 

        // If any requests return, we no longer respond to them.

        if (me.pageMap.events.pageadded) {

            me.pageMap.events.pageadded.clearListeners();

        }

 

        // Cancel all outstanding requests

        for (page in reqs) {

            if (reqs.hasOwnProperty(page)) {

                req = reqs[page];

                delete reqs[page];

                delete req.callback;

            }

        }

    },

/**

* 根据树JSON 中id 获取对应NODE

*

* 此方法会调用Ext.data.Tree中的getNodeById

*

*/

getNodeById: function (id) {

return this.tree.getNodeById(id);

}

}, function() {

    var proto = this.prototype;

    proto.indexSorter = new Ext.util.Sorter({

        sorterFn: proto.sortByIndex

    });

 

    /**

     * @class Ext.data.Store.PageMap

     * @extends Ext.util.LruCache

     * Private class for use by only Store when configured `buffered: true`.

     * @private

     */

    this.prototype.PageMap = new Ext.Class({

        extend: 'Ext.util.LruCache',

 

        // Maintain a generation counter, so that the Store can reject incoming pages destined for the previous generation

        clear: function(initial) {

            this.generation = (this.generation ||0) + 1;

            this.callParent(arguments);

        },

 

        getPageFromRecordIndex: this.prototype.getPageFromRecordIndex,

 

        addPage: function(page, records) {

            this.add(page, records);

            this.fireEvent('pageAdded', page, records);

        },

 

        getPage: function(page) {

            return this.get(page);

        },

 

        hasRange: function(start, end) {

            var page = this.getPageFromRecordIndex(start),

                endPage = this.getPageFromRecordIndex(end);

 

            for (; page <= endPage; page++) {

                if (!this.hasPage(page)) {

                    return false;

                }

            }

            return true;

        },

 

        hasPage: function(page) {

            // We must use this.get to trigger an access so that the page which is checked for presence is not eligible for pruning

            return !!this.get(page);

        },

 

        getRange: function(start, end) {

            if (!this.hasRange(start, end)) {

                Ext.Error.raise('PageMap asked for range which it does not have');

            }

            var me = this,

                startPage = me.getPageFromRecordIndex(start),

                endPage = me.getPageFromRecordIndex(end),

                dataStart = (startPage - 1) * me.pageSize,

                dataEnd = (endPage * me.pageSize) - 1,

                page = startPage,

                result = [],

                sliceBegin, sliceEnd, doSlice,

                i = 0, len;

 

            for (; page <= endPage; page++) {

 

                // First and last pages will need slicing to cut into the actual wanted records

                if (page == startPage) {

                    sliceBegin = start - dataStart;

                    doSlice = true;

                } else {

                    sliceBegin = 0;

                    doSlice = false;

                }

                if (page == endPage) {

                    sliceEnd = me.pageSize - (dataEnd - end);

                    doSlice = true;

                }

 

                // First and last pages will need slicing

                if (doSlice) {

                    Ext.Array.push(result, Ext.Array.slice(me.getPage(page), sliceBegin, sliceEnd));

                } else {

                    Ext.Array.push(result, me.getPage(page));

                }

            }

 

            // Inject the dataset ordinal position into the record as the index

            for (len = result.length; i < len; i++) {

                result[i].index = start++;

            }

            return result;

        }

    });

});

分享到:
评论

相关推荐

    Extjs2分页树 带查询功能

    2. **树存储**:创建一个继承自Ext.data.TreeStore的子类,增加分页逻辑。这可能涉及到重写`loadData`方法,以便在每次加载新页面时只获取当前页的数据。 3. **查询功能**:添加搜索框(Ext.form.TextField)并监听...

    ext TreeGrid分页可编辑

    - 在Ext TreeGrid中实现分页功能通常需要使用到两个Store:一个是用于处理树形数据的`TreeStore`,另一个则是用于处理分页逻辑的普通`JsonStore`。 3. **自定义序号**: - 为了确保在分页的情况下,每一页的序号...

    Ext Js权威指南(.zip.001

    7.5.7 store的分页 / 359 7.5.8 store的排序:ext.util.sorter与ext.util.sortable / 360 7.5.9 store的过滤:ext.util.filter / 363 7.5.10 store的分组:ext.util.grouper / 363 7.5.11 树节点:ext.data....

    SNS单模无芯光纤仿真与传感器结构特性分析——基于Rsoft beamprop模块

    内容概要:本文主要探讨了SNS单模无芯光纤的仿真分析及其在通信和传感领域的应用潜力。首先介绍了模间干涉仿真的重要性,利用Rsoft beamprop模块模拟不同模式光在光纤中的传播情况,进而分析光纤的传输性能和模式特性。接着讨论了光纤传输特性的仿真,包括损耗、色散和模式耦合等参数的评估。随后,文章分析了光纤的结构特性,如折射率分布、包层和纤芯直径对性能的影响,并探讨了镀膜技术对光纤性能的提升作用。最后,进行了变形仿真分析,研究外部因素导致的光纤变形对其性能的影响。通过这些分析,为优化光纤设计提供了理论依据。 适合人群:从事光纤通信、光学工程及相关领域的研究人员和技术人员。 使用场景及目标:适用于需要深入了解SNS单模无芯光纤特性和优化设计的研究项目,旨在提高光纤性能并拓展其应用场景。 其他说明:本文不仅提供了详细的仿真方法和技术细节,还对未来的发展方向进行了展望,强调了SNS单模无芯光纤在未来通信和传感领域的重要地位。

    发那科USM通讯程序socket-rece

    发那科USM通讯程序socket-set

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    嵌入式八股文面试题库资料知识宝典-WIFI.zip

    JS+HTML源码与image

    源码与image

    物流行业车辆路径优化:基于遗传算法和其他优化算法的MATLAB实现及应用

    内容概要:本文详细探讨了物流行业中路径规划与车辆路径优化(VRP)的问题,特别是针对冷链物流、带时间窗的车辆路径优化(VRPTW)、考虑充电桩的车辆路径优化(EVRP)以及多配送中心情况下的路径优化。文中不仅介绍了遗传算法、蚁群算法、粒子群算法等多种优化算法的理论背景,还提供了完整的MATLAB代码及注释,帮助读者理解这些算法的具体实现。此外,文章还讨论了如何通过MATLAB处理大量数据和复杂计算,以得出最优的路径方案。 适合人群:从事物流行业的研究人员和技术人员,尤其是对路径优化感兴趣的开发者和工程师。 使用场景及目标:适用于需要优化车辆路径的企业和个人,旨在提高配送效率、降低成本、确保按时交付货物。通过学习本文提供的算法和代码,读者可以在实际工作中应用这些优化方法,提升物流系统的性能。 其他说明:为了更好地理解和应用这些算法,建议读者参考相关文献和教程进行深入学习。同时,实际应用中还需根据具体情况进行参数调整和优化。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_8.doc.zip

    基于灰狼优化算法的城市路径规划Matlab实现——解决TSP问题

    内容概要:本文介绍了基于灰狼优化算法(GWO)的城市路径规划优化问题(TSP),并通过Matlab实现了该算法。文章详细解释了GWO算法的工作原理,包括寻找猎物、围捕猎物和攻击猎物三个阶段,并提供了具体的代码示例。通过不断迭代优化路径,最终得到最优的城市路径规划方案。与传统TSP求解方法相比,GWO算法具有更好的全局搜索能力和较快的收敛速度,适用于复杂的城市环境。尽管如此,算法在面对大量城市节点时仍面临运算时间和参数设置的挑战。 适合人群:对路径规划、优化算法感兴趣的科研人员、学生以及从事交通规划的专业人士。 使用场景及目标:①研究和开发高效的路径规划算法;②优化城市交通系统,提升出行效率;③探索人工智能在交通领域的应用。 其他说明:文中提到的代码可以作为学习和研究的基础,但实际应用中需要根据具体情况调整算法参数和优化策略。

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-Intel3.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-2019京东C++.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    嵌入式八股文面试题库资料知识宝典-北京光桥科技有限公司面试题.zip

    物理学领域十字形声子晶体的能带与传输特性研究及应用

    内容概要:本文详细探讨了十字形声子晶体的能带结构和传输特性。首先介绍了声子晶体作为新型周期性结构在物理学和工程学中的重要地位,特别是十字形声子晶体的独特结构特点。接着从散射体的形状、大小、排列周期等方面分析了其对能带结构的影响,并通过理论计算和仿真获得了能带图。随后讨论了十字形声子晶体的传输特性,即它对声波的调控能力,包括传播速度、模式和能量分布的变化。最后通过大量实验和仿真验证了理论分析的正确性,并得出结论指出散射体的材料、形状和排列方式对其性能有重大影响。 适合人群:从事物理学、材料科学、声学等相关领域的研究人员和技术人员。 使用场景及目标:适用于希望深入了解声子晶体尤其是十字形声子晶体能带与传输特性的科研工作者,旨在为相关领域的创新和发展提供理论支持和技术指导。 其他说明:文中还对未来的研究方向进行了展望,强调了声子晶体在未来多个领域的潜在应用价值。

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_.zip

    嵌入式系统开发_USB主机控制器_Arduino兼容开源硬件_基于Mega32U4和MAX3421E芯片的USB设备扩展开发板_支持多种USB外设接入与控制的通用型嵌入式开发平台_

    e2b8a-main.zip

    e2b8a-main.zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    少儿编程scratch项目源代码文件案例素材-火柴人跑酷(2).zip

    【HarmonyOS分布式技术】远程启动子系统详解:跨设备无缝启动与智能协同的应用场景及未来展望

    内容概要:本文详细介绍了HarmonyOS分布式远程启动子系统,该系统作为HarmonyOS的重要组成部分,旨在打破设备间的界限,实现跨设备无缝启动、智能设备选择和数据同步与连续性等功能。通过分布式软总线和分布式数据管理技术,它能够快速、稳定地实现设备间的通信和数据同步,为用户提供便捷的操作体验。文章还探讨了该系统在智能家居、智能办公和教育等领域的应用场景,展示了其在提升效率和用户体验方面的巨大潜力。最后,文章展望了该系统的未来发展,强调其在技术优化和应用场景拓展上的无限可能性。 适合人群:对HarmonyOS及其分布式技术感兴趣的用户、开发者和行业从业者。 使用场景及目标:①理解HarmonyOS分布式远程启动子系统的工作原理和技术细节;②探索该系统在智能家居、智能办公和教育等领域的具体应用场景;③了解该系统为开发者提供的开发优势和实践要点。 其他说明:本文不仅介绍了HarmonyOS分布式远程启动子系统的核心技术和应用场景,还展望了其未来的发展方向。通过阅读本文,用户可以全面了解该系统如何通过技术创新提升设备间的协同能力和用户体验,为智能生活带来新的变革。

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

    嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_1.zip

Global site tag (gtag.js) - Google Analytics