diff --git a/.eslintrc.json b/.eslintrc.json index e852f7f63c..63ccb63768 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -159,7 +159,6 @@ "jQuery": false, "lightbox": false, "list_util": false, - "ListWidget": false, "localStorage": false, "location": false, "message_events": false, diff --git a/frontend_tests/node_tests/dropdown_list_widget.js b/frontend_tests/node_tests/dropdown_list_widget.js index 44e3481363..3153b1d854 100644 --- a/frontend_tests/node_tests/dropdown_list_widget.js +++ b/frontend_tests/node_tests/dropdown_list_widget.js @@ -2,15 +2,20 @@ const {strict: assert} = require("assert"); -const {set_global, zrequire} = require("../zjsunit/namespace"); +const rewiremock = require("rewiremock/node"); + +const {zrequire} = require("../zjsunit/namespace"); const {run_test} = require("../zjsunit/test"); const $ = require("../zjsunit/zjquery"); const noop = () => {}; const _ListWidget = { + __esModule: true, create: () => ({init: noop}), }; -set_global("ListWidget", _ListWidget); +rewiremock("../../static/js/list_widget").with(_ListWidget); + +rewiremock.enable(); const dropdown_list_widget = zrequire("dropdown_list_widget"); @@ -74,3 +79,4 @@ run_test("no_default_value", () => { const widget = dropdown_list_widget(opts); assert.equal(widget.value(), "null-value"); }); +rewiremock.disable(); diff --git a/frontend_tests/node_tests/recent_topics.js b/frontend_tests/node_tests/recent_topics.js index 56775df2e8..fd6ab3a00b 100644 --- a/frontend_tests/node_tests/recent_topics.js +++ b/frontend_tests/node_tests/recent_topics.js @@ -54,8 +54,10 @@ set_global("hash_util", { rewiremock("../../static/js/recent_senders").with({ get_topic_recent_senders: () => [1, 2], }); -const ListWidget = set_global("ListWidget", { +const ListWidget = { + __esModule: true, modifier: noop, + create: (container, mapped_topic_values, opts) => { const formatted_topics = []; ListWidget.modifier = opts.modifier; @@ -75,9 +77,11 @@ const ListWidget = set_global("ListWidget", { } return ListWidget; }, + hard_redraw: noop, render_item: (item) => ListWidget.modifier(item), -}); +}; +rewiremock("../../static/js/list_widget").with(ListWidget); rewiremock("../../static/js/drafts").with({ update_draft: noop, }); diff --git a/frontend_tests/node_tests/settings_org.js b/frontend_tests/node_tests/settings_org.js index 7d8e054887..b8c9f0ee0f 100644 --- a/frontend_tests/node_tests/settings_org.js +++ b/frontend_tests/node_tests/settings_org.js @@ -70,6 +70,7 @@ const _realm_logo = { }; const _ListWidget = { + __esModule: true, create: () => ({init: noop}), }; @@ -79,7 +80,7 @@ set_global("jQuery", _jQuery); rewiremock("../../static/js/loading").with(_loading); set_global("realm_logo", _realm_logo); set_global("ui_report", _ui_report); -set_global("ListWidget", _ListWidget); +rewiremock("../../static/js/list_widget").with(_ListWidget); // setup is only imported to set the // setup.password_change_in_progress flag. diff --git a/frontend_tests/node_tests/stream_edit.js b/frontend_tests/node_tests/stream_edit.js index a6ea433c6d..2a87fea88d 100644 --- a/frontend_tests/node_tests/stream_edit.js +++ b/frontend_tests/node_tests/stream_edit.js @@ -18,7 +18,7 @@ set_global("hash_util", { stream_edit_uri: noop, by_stream_uri: noop, }); -set_global("ListWidget", { +rewiremock("../../static/js/list_widget").with({ create: () => ({init: noop}), }); const page_params = set_global("page_params", {}); diff --git a/static/js/attachments_ui.js b/static/js/attachments_ui.js index aa3f4d1932..c15378fb26 100644 --- a/static/js/attachments_ui.js +++ b/static/js/attachments_ui.js @@ -4,6 +4,7 @@ const render_settings_upload_space_stats = require("../templates/settings/upload const render_uploaded_files_list = require("../templates/uploaded_files_list.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); let attachments; diff --git a/static/js/bundles/app.js b/static/js/bundles/app.js index 056caf0738..5d714450f1 100644 --- a/static/js/bundles/app.js +++ b/static/js/bundles/app.js @@ -26,7 +26,6 @@ import "../narrow"; import "../reload"; import "../compose_actions"; import "../subs"; -import "../list_widget"; import "../floating_recipient_bar"; import "../lightbox"; import "../ui_report"; diff --git a/static/js/dropdown_list_widget.js b/static/js/dropdown_list_widget.js index ca83ac4d9a..63c966cc6a 100644 --- a/static/js/dropdown_list_widget.js +++ b/static/js/dropdown_list_widget.js @@ -2,6 +2,8 @@ const render_dropdown_list = require("../templates/settings/dropdown_list.hbs"); +const ListWidget = require("./list_widget"); + const DropdownListWidget = function (opts) { const init = () => { // Run basic sanity checks on opts, and set up sane defaults. diff --git a/static/js/global.d.ts b/static/js/global.d.ts index abf75c37a3..72d2dad331 100644 --- a/static/js/global.d.ts +++ b/static/js/global.d.ts @@ -35,7 +35,6 @@ declare let info_overlay: any; declare let input_pill: any; declare let lightbox: any; declare let list_util: any; -declare let list_widget: any; declare let message_events: any; declare let message_fetch: any; declare let message_flags: any; diff --git a/static/js/list_widget.js b/static/js/list_widget.js index d45103fed5..abec46d568 100644 --- a/static/js/list_widget.js +++ b/static/js/list_widget.js @@ -1,5 +1,3 @@ -"use strict"; - const DEFAULTS = { INITIAL_RENDER_COUNT: 80, LOAD_COUNT: 20, @@ -10,7 +8,7 @@ const DEFAULTS = { // This function describes (programmatically) how to use the ListWidget. // ---------------------------------------------------- -exports.validate_opts = (opts) => { +export function validate_opts(opts) { if (opts.html_selector && typeof opts.html_selector !== "function") { // We have an html_selector, but it is not a function. // This is a programming error. @@ -22,9 +20,9 @@ exports.validate_opts = (opts) => { return false; } return true; -}; +} -exports.get_filtered_items = (value, list, opts) => { +export function get_filtered_items(value, list, opts) { /* This is used by the main object (see `create`), but we split it out to make it a bit easier @@ -65,10 +63,10 @@ exports.get_filtered_items = (value, list, opts) => { } return list.filter((item) => predicate(item)); -}; +} -exports.alphabetic_sort = (prop) => - function (a, b) { +export function alphabetic_sort(prop) { + return function (a, b) { // The conversion to uppercase helps make the sorting case insensitive. const str1 = a[prop].toUpperCase(); const str2 = b[prop].toUpperCase(); @@ -81,9 +79,10 @@ exports.alphabetic_sort = (prop) => return -1; }; +} -exports.numeric_sort = (prop) => - function (a, b) { +export function numeric_sort(prop) { + return function (a, b) { if (Number.parseFloat(a[prop]) > Number.parseFloat(b[prop])) { return 1; } else if (Number.parseFloat(a[prop]) === Number.parseFloat(b[prop])) { @@ -92,8 +91,9 @@ exports.numeric_sort = (prop) => return -1; }; +} -exports.valid_filter_opts = (opts) => { +export function valid_filter_opts(opts) { if (!opts.filter) { return true; } @@ -114,19 +114,19 @@ exports.valid_filter_opts = (opts) => { } return true; -}; +} // @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) { +export function create($container, list, opts) { if (!opts) { blueslip.error("Need opts to create widget."); return undefined; } - if (!exports.validate_opts(opts)) { + if (!validate_opts(opts)) { return undefined; } @@ -140,8 +140,8 @@ exports.create = function ($container, list, opts) { sorting_function: null, sorting_functions: new Map(), generic_sorting_functions: { - alphabetic: exports.alphabetic_sort, - numeric: exports.numeric_sort, + alphabetic: alphabetic_sort, + numeric: numeric_sort, }, offset: 0, list, @@ -150,7 +150,7 @@ exports.create = function ($container, list, opts) { filter_value: "", }; - if (!exports.valid_filter_opts(opts)) { + if (!valid_filter_opts(opts)) { return undefined; } @@ -162,7 +162,7 @@ exports.create = function ($container, list, opts) { const widget = {}; widget.filter_and_sort = function () { - meta.filtered_list = exports.get_filtered_items(meta.filter_value, meta.list, opts); + meta.filtered_list = get_filtered_items(meta.filter_value, meta.list, opts); if (meta.sorting_function) { meta.filtered_list.sort(meta.sorting_function); @@ -276,7 +276,7 @@ exports.create = function ($container, list, opts) { if (opts.parent_container) { opts.parent_container.on("click.list_widget_sort", "[data-sort]", function () { - exports.handle_sort($(this), widget); + handle_sort($(this), widget); }); } @@ -349,13 +349,13 @@ exports.create = function ($container, list, opts) { } return widget; -}; +} -exports.get = function (name) { +export function get(name) { return DEFAULTS.instances.get(name) || false; -}; +} -exports.handle_sort = function (th, list) { +export function handle_sort(th, list) { /* one would specify sort parameters like this: - name => sort alphabetic. @@ -388,6 +388,4 @@ exports.handle_sort = function (th, list) { // if `prop_name` is defined, it will trigger the generic codepath, // and not if it is undefined. list.sort(sort_type, prop_name); -}; - -window.ListWidget = exports; +} diff --git a/static/js/muting_ui.js b/static/js/muting_ui.js index 9f510b6773..a4b79b3c3d 100644 --- a/static/js/muting_ui.js +++ b/static/js/muting_ui.js @@ -3,6 +3,7 @@ import render_topic_muted from "../templates/topic_muted.hbs"; import * as channel from "./channel"; import * as feedback_widget from "./feedback_widget"; +import * as ListWidget from "./list_widget"; import * as muting from "./muting"; import * as settings_muting from "./settings_muting"; import * as stream_data from "./stream_data"; diff --git a/static/js/recent_topics.js b/static/js/recent_topics.js index 262b578b60..92735cbd0b 100644 --- a/static/js/recent_topics.js +++ b/static/js/recent_topics.js @@ -5,6 +5,7 @@ const render_recent_topics_filters = require("../templates/recent_topics_filters const render_recent_topics_body = require("../templates/recent_topics_table.hbs"); const drafts = require("./drafts"); +const ListWidget = require("./list_widget"); const {localstorage} = require("./localstorage"); const muting = require("./muting"); const narrow_state = require("./narrow_state"); diff --git a/static/js/settings_emoji.js b/static/js/settings_emoji.js index ba1e67bf67..bec26abb92 100644 --- a/static/js/settings_emoji.js +++ b/static/js/settings_emoji.js @@ -5,6 +5,7 @@ const render_admin_emoji_list = require("../templates/admin_emoji_list.hbs"); const render_settings_emoji_settings_tip = require("../templates/settings/emoji_settings_tip.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const people = require("./people"); diff --git a/static/js/settings_exports.js b/static/js/settings_exports.js index c0bdabb650..4851bc2192 100644 --- a/static/js/settings_exports.js +++ b/static/js/settings_exports.js @@ -3,6 +3,7 @@ const render_admin_export_list = require("../templates/admin_export_list.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const people = require("./people"); diff --git a/static/js/settings_invites.js b/static/js/settings_invites.js index ac57b3da73..89f4d26904 100644 --- a/static/js/settings_invites.js +++ b/static/js/settings_invites.js @@ -4,6 +4,7 @@ const render_admin_invites_list = require("../templates/admin_invites_list.hbs") const render_settings_revoke_invite_modal = require("../templates/settings/revoke_invite_modal.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const people = require("./people"); const settings_config = require("./settings_config"); diff --git a/static/js/settings_linkifiers.js b/static/js/settings_linkifiers.js index 18ae56a0f3..b7b79ccd80 100644 --- a/static/js/settings_linkifiers.js +++ b/static/js/settings_linkifiers.js @@ -3,6 +3,7 @@ const render_admin_filter_list = require("../templates/admin_filter_list.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const meta = { diff --git a/static/js/settings_streams.js b/static/js/settings_streams.js index 82e6963a05..06ef613592 100644 --- a/static/js/settings_streams.js +++ b/static/js/settings_streams.js @@ -3,6 +3,7 @@ const render_admin_default_streams_list = require("../templates/admin_default_streams_list.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const stream_data = require("./stream_data"); diff --git a/static/js/settings_users.js b/static/js/settings_users.js index 99c98e101e..ccf415e2ce 100644 --- a/static/js/settings_users.js +++ b/static/js/settings_users.js @@ -5,6 +5,7 @@ const render_admin_human_form = require("../templates/admin_human_form.hbs"); const render_admin_user_list = require("../templates/admin_user_list.hbs"); const channel = require("./channel"); +const ListWidget = require("./list_widget"); const loading = require("./loading"); const people = require("./people"); const settings_config = require("./settings_config"); diff --git a/static/js/stream_edit.js b/static/js/stream_edit.js index 850a9b0b57..64d40b10b9 100644 --- a/static/js/stream_edit.js +++ b/static/js/stream_edit.js @@ -5,6 +5,7 @@ import render_subscription_settings from "../templates/subscription_settings.hbs import render_subscription_stream_privacy_modal from "../templates/subscription_stream_privacy_modal.hbs"; import * as channel from "./channel"; +import * as ListWidget from "./list_widget"; import * as narrow_state from "./narrow_state"; import * as peer_data from "./peer_data"; import * as people from "./people"; diff --git a/static/js/stream_ui_updates.js b/static/js/stream_ui_updates.js index ff665d8cf0..7e0d2f40b4 100644 --- a/static/js/stream_ui_updates.js +++ b/static/js/stream_ui_updates.js @@ -1,5 +1,6 @@ import render_subscription_type from "../templates/subscription_type.hbs"; +import * as ListWidget from "./list_widget"; import * as peer_data from "./peer_data"; import * as stream_data from "./stream_data"; import * as stream_edit from "./stream_edit";