<commit_before>const DEFAULTS = {
    INITIAL_RENDER_COUNT: 80,
    LOAD_COUNT: 20,
    instances: new Map(),
};

exports.filter = (value, list, opts) => {
    /*
        This is used by the main object (see `create`),
        but we split it out to make it a bit easier
        to test.
    */
    if (opts.filter.filterer) {
        return opts.filter.filterer(list, value);
    }

    const predicate = opts.filter.predicate;

    return list.filter(function (item) {
        return predicate(item, value);
    });
};

exports.validate_filter = (opts) => {
    if (!opts.filter) {
        return;
    }
    if (opts.filter.predicate) {
        if (typeof opts.filter.predicate !== 'function') {
            blueslip.error('Filter predicate function is missing.');
            return;
        }
        if (opts.filter.filterer) {
            blueslip.error('Filterer and predicate are mutually exclusive.');
            return;
        }
    } else {
        if (typeof opts.filter.filterer !== 'function') {
            blueslip.error('Filter filterer function is missing.');
            return;
        }
    }
};

// @params
// container: jQuery object to append to.
// list: The list of items to progressively append.
// opts: An object of random preferences.
exports.create = function ($container, list, opts) {
    // this memoizes the results and will return a previously invoked
    // instance's prototype.
    if (opts.name && DEFAULTS.instances.get(opts.name)) {
        // the false flag here means "don't run `init`". This is because a
        // user is likely reinitializing and will have put .init() afterwards.
        // This happens when the same codepath is hit multiple times.
        return DEFAULTS.instances.get(opts.name)
        // sets the container to the new container in this prototype's args.
            .set_container($container)
        // sets the input to the new input in the args.
            .set_opts(opts)
            .__set_events()
            .data(list)
            .init();
    }

    const meta = {
        sorting_function: null,
        prop: null,
        sorting_functions: new Map(),
        generic_sorting_functions: new Map(),
        offset: 0,
        list: list,
        filtered_list: list,

    };

    function filter_list(value) {
        meta.filtered_list = exports.filter(value, meta.list, opts);
    }

    if (!opts) {
        return;
    }
    exports.validate_filter(opts);

    const prototype = {
        // Reads the provided list (in the scope directly above)
        // and renders the next block of messages automatically
        // into the specified contianer.
        render: function (load_count) {
            load_count = load_count || opts.load_count || DEFAULTS.LOAD_COUNT;

            // Stop once the offset reaches the length of the original list.
            if (meta.offset >= meta.filtered_list.length) {
                return;
            }

            const slice = meta.filtered_list.slice(meta.offset, meta.offset + load_count);

            const finish = blueslip.start_timing('list_render ' + opts.name);
            let html = "";
            for (const item of slice) {
                let _item = opts.modifier(item);

                // if valid jQuery selection, attempt to grab all elements within
                // and string them together into a giant outerHTML fragment.
                if (_item.constructor === jQuery) {
                    _item = (function ($nodes) {
                        let html = "";
                        $nodes.each(function () {
                            if (this.nodeType === 1) {
                                html += this.outerHTML;
                            }
                        });

                        return html;
                    }(_item));
                }

                // if is a valid element, get the outerHTML.
                if (_item instanceof Element) {
                    _item = _item.outerHTML;
                }

                // append the HTML or nothing if corrupt (null, undef, etc.).
                html += _item || "";
            }

            finish();

            $container.append($(html));
            meta.offset += load_count;

            return this;
        },

        // Fills the container with an initial batch of items.
        // Needs to be enough to exceed the max height, so that a
        // scrollable area is created.
        init: function () {
            this.clear();
            this.render(DEFAULTS.INITIAL_RENDER_COUNT);
            return this;
        },

        filter: function (map_function) {
            meta.filtered_list = meta.list(map_function);
        },

        // reset the data associated with a list. This is so that instead of
        // initializing a new progressive list render instance, you can just
        // update the data of an existing one.
        data: function (...args) {
            // if no args are provided then just return the existing data.
            // this interface is similar to how many jQuery functions operate,
            // where a call to the method without data returns the existing data.
            if (args.length === 0) {
                return meta.list;
            }
            const [data] = args;

            if (Array.isArray(data)) {
                meta.list = data;

                if (opts.filter && opts.filter.element) {
                    const value = $(opts.filter.element).val().toLocaleLowerCase();
                    filter_list(value);
                }

                prototype.clear();

                return this;
            }

            blueslip.warn("The data object provided to the progressive" +
                              " list render is invalid");
            return this;
        },
<commit_msg>list_render: Reset Data for sorted tables.<commit_after>const DEFAULTS = {
    INITIAL_RENDER_COUNT: 80,
    LOAD_COUNT: 20,
    instances: new Map(),
};

exports.filter = (value, list, opts) => {
    /*
        This is used by the main object (see `create`),
        but we split it out to make it a bit easier
        to test.
    */
    if (opts.filter.filterer) {
        return opts.filter.filterer(list, value);
    }

    const predicate = opts.filter.predicate;

    return list.filter(function (item) {
        return predicate(item, value);
    });
};

exports.validate_filter = (opts) => {
    if (!opts.filter) {
        return;
    }
    if (opts.filter.predicate) {
        if (typeof opts.filter.predicate !== 'function') {
            blueslip.error('Filter predicate function is missing.');
            return;
        }
        if (opts.filter.filterer) {
            blueslip.error('Filterer and predicate are mutually exclusive.');
            return;
        }
    } else {
        if (typeof opts.filter.filterer !== 'function') {
            blueslip.error('Filter filterer function is missing.');
            return;
        }
    }
};

// @params
// container: jQuery object to append to.
// list: The list of items to progressively append.
// opts: An object of random preferences.
exports.create = function ($container, list, opts) {
    // this memoizes the results and will return a previously invoked
    // instance's prototype.
    if (opts.name && DEFAULTS.instances.get(opts.name)) {
        // the false flag here means "don't run `init`". This is because a
        // user is likely reinitializing and will have put .init() afterwards.
        // This happens when the same codepath is hit multiple times.
        return DEFAULTS.instances.get(opts.name)
        // sets the container to the new container in this prototype's args.
            .set_container($container)
        // sets the input to the new input in the args.
            .set_opts(opts)
            .__set_events()
            .data(list)
            .init();
    }

    const meta = {
        sorting_function: null,
        prop: null,
        sorting_functions: new Map(),
        generic_sorting_functions: new Map(),
        offset: 0,
        list: list,
        filtered_list: list,

    };

    function filter_list(value) {
        meta.filtered_list = exports.filter(value, meta.list, opts);
    }

    if (!opts) {
        return;
    }
    exports.validate_filter(opts);

    const prototype = {
        // Reads the provided list (in the scope directly above)
        // and renders the next block of messages automatically
        // into the specified contianer.
        render: function (load_count) {
            load_count = load_count || opts.load_count || DEFAULTS.LOAD_COUNT;

            // Stop once the offset reaches the length of the original list.
            if (meta.offset >= meta.filtered_list.length) {
                return;
            }

            const slice = meta.filtered_list.slice(meta.offset, meta.offset + load_count);

            const finish = blueslip.start_timing('list_render ' + opts.name);
            let html = "";
            for (const item of slice) {
                let _item = opts.modifier(item);

                // if valid jQuery selection, attempt to grab all elements within
                // and string them together into a giant outerHTML fragment.
                if (_item.constructor === jQuery) {
                    _item = (function ($nodes) {
                        let html = "";
                        $nodes.each(function () {
                            if (this.nodeType === 1) {
                                html += this.outerHTML;
                            }
                        });

                        return html;
                    }(_item));
                }

                // if is a valid element, get the outerHTML.
                if (_item instanceof Element) {
                    _item = _item.outerHTML;
                }

                // append the HTML or nothing if corrupt (null, undef, etc.).
                html += _item || "";
            }

            finish();

            $container.append($(html));
            meta.offset += load_count;

            return this;
        },

        // Fills the container with an initial batch of items.
        // Needs to be enough to exceed the max height, so that a
        // scrollable area is created.
        init: function () {
            this.clear();
            this.render(DEFAULTS.INITIAL_RENDER_COUNT);
            return this;
        },

        filter: function (map_function) {
            meta.filtered_list = meta.list(map_function);
        },

        // reset the data associated with a list. This is so that instead of
        // initializing a new progressive list render instance, you can just
        // update the data of an existing one.
        data: function (...args) {
            // if no args are provided then just return the existing data.
            // this interface is similar to how many jQuery functions operate,
            // where a call to the method without data returns the existing data.
            if (args.length === 0) {
                return meta.list;
            }
            const [data] = args;

            if (Array.isArray(data)) {
                meta.list = data;
                meta.filtered_list = data;

                if (opts.filter && opts.filter.element) {
                    const value = $(opts.filter.element).val().toLocaleLowerCase();
                    filter_list(value);
                }

                prototype.clear();

                return this;
            }

            blueslip.warn("The data object provided to the progressive" +
                              " list render is invalid");
            return this;
        },

{'fraction_non_alphanumeric': 0.09646878198567042, 'fraction_numerical': 0.001194131695667008, 'mean_word_length': 1.5220477522047753, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4299612', 'n_tokens_mistral': 3029, 'n_tokens_neox': 2906, 'n_words': 975}