/sdk/src/mixin/Sortable.js
https://bitbucket.org/mobile_venkys/mobisale1 · JavaScript · 341 lines · 183 code · 44 blank · 114 comment · 39 complexity · 1cd53e5788fcf0f6106c06dec7e434e7 MD5 · raw file
- /**
- * @private
- */
- Ext.define('Ext.mixin.Sortable', {
- extend: 'Ext.mixin.Mixin',
- requires: [
- 'Ext.util.Sorter'
- ],
- mixinConfig: {
- id: 'sortable'
- },
- config: {
- /**
- * @cfg {Array} sorters
- * An array with sorters. A sorter can be an instance of Ext.util.Sorter, a string
- * indicating a property name, an object representing an Ext.util.Sorter configuration,
- * or a sort function.
- */
- sorters: null,
- /**
- * @cfg {String} defaultSortDirection
- * The default sort direction to use if one is not specified (defaults to "ASC")
- */
- defaultSortDirection: "ASC",
- /**
- * @cfg {String} sortRoot
- * The root inside each item in which the properties exist that we want to sort on.
- * This is useful for sorting records in which the data exists inside a 'data' property.
- */
- sortRoot: null
- },
- /**
- * @property {Boolean} dirtySortFn
- * A flag indicating wether the currently cashed sort function is still valid. Read-only.
- */
- dirtySortFn: false,
- /**
- * @property currentSortFn
- * This is the cached sorting function which is a generated function that calls all the
- * configured sorters in the correct order. This is a read-only property.
- */
- sortFn: null,
- /**
- * @property {Boolean} sorted
- * A read-only flag indicating if this object is sorted
- */
- sorted: false,
- applySorters: function(sorters, collection) {
- if (!collection) {
- collection = this.createSortersCollection();
- }
- collection.clear();
- this.sorted = false;
- if (sorters) {
- this.addSorters(sorters);
- }
- return collection;
- },
- createSortersCollection: function() {
- this._sorters = Ext.create('Ext.util.Collection', function(sorter) {
- return sorter.getId();
- });
- return this._sorters;
- },
- /**
- * This method adds a sorter.
- * @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of
- * Ext.util.Sorter, a string indicating a property name, an object representing an Ext.util.Sorter
- * configuration, or a sort function.
- * @param {String} defaultDirection The default direction for each sorter in the array. Defaults
- * to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
- */
- addSorter: function(sorter, defaultDirection) {
- this.addSorters([sorter], defaultDirection);
- },
- /**
- * This method adds all the sorters in a passed array.
- * @param {Array} sorters An array with sorters. A sorter can be an instance of Ext.util.Sorter, a string
- * indicating a property name, an object representing an Ext.util.Sorter configuration,
- * or a sort function.
- * @param {String} defaultDirection The default direction for each sorter in the array. Defaults
- * to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
- */
- addSorters: function(sorters, defaultDirection) {
- var currentSorters = this.getSorters();
- return this.insertSorters(currentSorters ? currentSorters.length : 0, sorters, defaultDirection);
- },
- /**
- * This method adds a sorter at a given index.
- * @param {Number} index The index at which to insert the sorter.
- * @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of Ext.util.Sorter,
- * a string indicating a property name, an object representing an Ext.util.Sorter configuration,
- * or a sort function.
- * @param {String} defaultDirection The default direction for each sorter in the array. Defaults
- * to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
- */
- insertSorter: function(index, sorter, defaultDirection) {
- return this.insertSorters(index, [sorter], defaultDirection);
- },
- /**
- * This method inserts all the sorters in the passed array at the given index.
- * @param {Number} index The index at which to insert the sorters.
- * @param {Array} sorters Can be an instance of Ext.util.Sorter, a string indicating a property name,
- * an object representing an Ext.util.Sorter configuration, or a sort function.
- * @param {String} defaultDirection The default direction for each sorter in the array. Defaults
- * to the value of {@link #defaultSortDirection}. Can be either 'ASC' or 'DESC'.
- */
- insertSorters: function(index, sorters, defaultDirection) {
- // We begin by making sure we are dealing with an array of sorters
- if (!Ext.isArray(sorters)) {
- sorters = [sorters];
- }
- var ln = sorters.length,
- direction = defaultDirection || this.getDefaultSortDirection(),
- sortRoot = this.getSortRoot(),
- currentSorters = this.getSorters(),
- newSorters = [],
- sorterConfig, i, sorter, currentSorter;
- if (!currentSorters) {
- // This will guarantee that we get the collection
- currentSorters = this.createSortersCollection();
- }
- // We first have to convert every sorter into a proper Sorter instance
- for (i = 0; i < ln; i++) {
- sorter = sorters[i];
- sorterConfig = {
- direction: direction,
- root: sortRoot
- };
- // If we are dealing with a string we assume it is a property they want to sort on.
- if (typeof sorter === 'string') {
- currentSorter = currentSorters.get(sorter);
- if (!currentSorter) {
- sorterConfig.property = sorter;
- } else {
- if (defaultDirection) {
- currentSorter.setDirection(defaultDirection);
- } else {
- // If we already have a sorter for this property we just toggle its direction.
- currentSorter.toggle();
- }
- continue;
- }
- }
- // If it is a function, we assume its a sorting function.
- else if (Ext.isFunction(sorter)) {
- sorterConfig.sorterFn = sorter;
- }
- // If we are dealing with an object, we assume its a Sorter configuration. In this case
- // we create an instance of Sorter passing this configuration.
- else if (Ext.isObject(sorter)) {
- if (!sorter.isSorter) {
- if (sorter.fn) {
- sorter.sorterFn = sorter.fn;
- delete sorter.fn;
- }
- sorterConfig = Ext.apply(sorterConfig, sorter);
- }
- else {
- newSorters.push(sorter);
- if (!sorter.getRoot()) {
- sorter.setRoot(sortRoot);
- }
- continue;
- }
- }
- // Finally we get to the point where it has to be invalid
- // <debug>
- else {
- Ext.Logger.warn('Invalid sorter specified:', sorter);
- }
- // </debug>
- // If a sorter config was created, make it an instance
- sorter = Ext.create('Ext.util.Sorter', sorterConfig);
- newSorters.push(sorter);
- }
- // Now lets add the newly created sorters.
- for (i = 0, ln = newSorters.length; i < ln; i++) {
- currentSorters.insert(index + i, newSorters[i]);
- }
- this.dirtySortFn = true;
- if (currentSorters.length) {
- this.sorted = true;
- }
- return currentSorters;
- },
- /**
- * This method removes a sorter.
- * @param {Ext.util.Sorter/String/Function/Object} sorter Can be an instance of Ext.util.Sorter,
- * a string indicating a property name, an object representing an Ext.util.Sorter configuration,
- * or a sort function.
- */
- removeSorter: function(sorter) {
- return this.removeSorters([sorter]);
- },
- /**
- * This method removes all the sorters in a passed array.
- * @param {Array} sorters Each value in the array can be a string (property name),
- * function (sorterFn) or {@link Ext.util.Sorter Sorter} instance.
- */
- removeSorters: function(sorters) {
- // We begin by making sure we are dealing with an array of sorters
- if (!Ext.isArray(sorters)) {
- sorters = [sorters];
- }
- var ln = sorters.length,
- currentSorters = this.getSorters(),
- i, sorter;
- for (i = 0; i < ln; i++) {
- sorter = sorters[i];
- if (typeof sorter === 'string') {
- currentSorters.removeAtKey(sorter);
- }
- else if (typeof sorter === 'function') {
- currentSorters.each(function(item) {
- if (item.getSorterFn() === sorter) {
- currentSorters.remove(item);
- }
- });
- }
- else if (sorter.isSorter) {
- currentSorters.remove(sorter);
- }
- }
- if (!currentSorters.length) {
- this.sorted = false;
- }
- },
- /**
- * This updates the cached sortFn based on the current sorters.
- * @return {Function} sortFn The generated sort function.
- * @private
- */
- updateSortFn: function() {
- var sorters = this.getSorters().items;
- this.sortFn = function(r1, r2) {
- var ln = sorters.length,
- result, i;
- // We loop over each sorter and check if r1 should be before or after r2
- for (i = 0; i < ln; i++) {
- result = sorters[i].sort.call(this, r1, r2);
- // If the result is -1 or 1 at this point it means that the sort is done.
- // Only if they are equal (0) we continue to see if a next sort function
- // actually might find a winner.
- if (result !== 0) {
- break;
- }
- }
- return result;
- };
- this.dirtySortFn = false;
- return this.sortFn;
- },
- /**
- * Returns an up to date sort function.
- * @return {Function} sortFn The sort function.
- */
- getSortFn: function() {
- if (this.dirtySortFn) {
- return this.updateSortFn();
- }
- return this.sortFn;
- },
- /**
- * This method will sort an array based on the currently configured {@link #sorters}.
- * @param {Array} data The array you want to have sorted
- * @return {Array} data The array you passed after it is sorted
- */
- sort: function(data) {
- Ext.Array.sort(data, this.getSortFn());
- return data;
- },
- /**
- * This method returns the index that a given item would be inserted into a given array based
- * on the current sorters.
- * @param {Array} items The array that you want to insert the item into.
- * @param {Mixed} item The item that you want to insert into the items array.
- * @returns {Number} index The index for the given item in the given array based on the current sorters.
- */
- findInsertionIndex: function(items, item, sortFn) {
- var start = 0,
- end = items.length - 1,
- sorterFn = sortFn || this.getSortFn(),
- middle,
- comparison;
- while (start <= end) {
- middle = (start + end) >> 1;
- comparison = sorterFn(item, items[middle]);
- if (comparison >= 0) {
- start = middle + 1;
- } else if (comparison < 0) {
- end = middle - 1;
- }
- }
- return start;
- }
- });