#

API Docs for: 3.10.3
Show: Inherited Protected Private Deprecated

# File: recordset/js/recordset-sort.js

    /**
     * Adds default and custom sorting functionality to the Recordset utility
     * @module recordset
     * @submodule recordset-sort
     */

    var Compare = Y.ArraySort.compare,
    isValue = Y.Lang.isValue;

    /**
     * Plugin that adds default and custom sorting functionality to the Recordset utility
     * @class RecordsetSort
     */

    function RecordsetSort(field, desc, sorter) {
        RecordsetSort.superclass.constructor.apply(this, arguments);
    }

    Y.mix(RecordsetSort, {
        NS: "sort",

        NAME: "recordsetSort",

        ATTRS: {

            /**
            * @description The last properties used to sort. Consists of an object literal with the keys "field", "desc", and "sorter"
            *
            * @attribute lastSortProperties
            * @public
            * @type object
            */
            lastSortProperties: {
                value: {
                    field: undefined,
                    desc: true,
                    sorter: undefined
                },
                validator: function(v) {
                    return (isValue(v.field) && isValue(v.desc) && isValue(v.sorter));
                }
            },

            /**
            * @description Default sort function to use if none is specified by the user.
            * Takes two records, the key to sort by, and whether sorting direction is descending or not (boolean).
            * If two records have the same value for a given key, the ID is used as the tie-breaker.
            *
            * @attribute defaultSorter
            * @public
            * @type function
            */
            defaultSorter: {
                value: function(recA, recB, field, desc) {
                    var sorted = Compare(recA.getValue(field), recB.getValue(field), desc);
                    if (sorted === 0) {
                        return Compare(recA.get("id"), recB.get("id"), desc);
                    }
                    else {
                        return sorted;
                    }
                }
            },

            /**
            * @description A boolean telling if the recordset is in a sorted state.
            *
            * @attribute defaultSorter
            * @public
            * @type function
            */
            isSorted: {
                value: false
            }
        }
    });

    Y.extend(RecordsetSort, Y.Plugin.Base, {

        /**
         * @description Sets up the default function to use when the "sort" event is fired.
         *
         * @method initializer
         * @protected
         */
        initializer: function(config) {

            var self = this,
            host = this.get('host');

            this.publish("sort", {
                defaultFn: Y.bind("_defSortFn", this)
            });

            //Toggle the isSorted ATTR based on events.
            //Remove events dont affect isSorted, as they are just popped/sliced out
            this.on("sort",
            function() {
                self.set('isSorted', true);
            });

            this.onHostEvent('add',
            function() {
                self.set('isSorted', false);
            },
            host);
            this.onHostEvent('update',
            function() {
                self.set('isSorted', false);
            },
            host);

        },

        destructor: function(config) {
            },

        /**
         * @description Method that all sort calls go through.
         * Sets up the lastSortProperties object with the details of the sort, and passes in parameters
         * to the "defaultSorter" or a custom specified sort function.
         *
         * @method _defSortFn
         * @private
         */
        _defSortFn: function(e) {
            //have to work directly with _items here - changing the recordset.
            this.get("host")._items.sort(function(a, b) {
                return (e.sorter)(a, b, e.field, e.desc);
            });

            this.set('lastSortProperties', e);
        },

        /**
         * @description Sorts the recordset.
         *
         * @method sort
         * @param field {string} A key to sort by.
         * @param desc {boolean} True if you want sort order to be descending, false if you want sort order to be ascending
         * @public
         */
        sort: function(field, desc, sorter) {
            this.fire("sort", {
                field: field,
                desc: desc,
                sorter: sorter || this.get("defaultSorter")
            });
        },

        /**
         * @description Resorts the recordset based on the last-used sort parameters (stored in 'lastSortProperties' ATTR)
         *
         * @method resort
         * @public
         */
        resort: function() {
            var p = this.get('lastSortProperties');
            this.fire("sort", {
                field: p.field,
                desc: p.desc,
                sorter: p.sorter || this.get("defaultSorter")
            });
        },

        /**
         * @description Reverses the recordset calling the standard array.reverse() method.
         *
         * @method reverse
         * @public
         */
        reverse: function() {
            this.get('host')._items.reverse();
        },

        /**
         * @description Sorts the recordset based on the last-used sort parameters, but flips the order. (ie: Descending becomes ascending, and vice versa).
         *
         * @method flip
         * @public
         */
        flip: function() {
            var p = this.get('lastSortProperties');

            //If a predefined field is not provided by which to sort by, throw an error
            if (isValue(p.field)) {
                this.fire("sort", {
                    field: p.field,
                    desc: !p.desc,
                    sorter: p.sorter || this.get("defaultSorter")
                });
            }
            else {
                Y.log('You called flip before setting a field by which to sort by. Maybe you meant to call reverse().');
            }
        }
    });

    Y.namespace("Plugin").RecordsetSort = RecordsetSort;