js: Prefix jQuery object variable names with $.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2022-01-25 02:36:19 -08:00
parent f21842e920
commit f84a2c08d5
195 changed files with 4883 additions and 4835 deletions

View File

@@ -18,9 +18,9 @@ The pills will automatically be inserted in before the ".input" in order.
## Basic usage ## Basic usage
```js ```js
var pill_containter = $("#input_container"); var $pill_containter = $("#input_container");
var pills = input_pill.create({ var pills = input_pill.create({
container: pill_container, $container: $pill_container,
create_item_from_text: user_pill.create_item_from_email, create_item_from_text: user_pill.create_item_from_email,
get_text_from_item: user_pill.get_email_from_item, get_text_from_item: user_pill.get_email_from_item,
}); });

View File

@@ -312,7 +312,7 @@ The code in `static/js/zform.js` renders the form (not
shown here) and then sets up a click handler like below: shown here) and then sets up a click handler like below:
```js ```js
elem.find('button').on('click', function (e) { $elem.find('button').on('click', function (e) {
e.stopPropagation(); e.stopPropagation();
// Grab our index from the markup. // Grab our index from the markup.

View File

@@ -8,8 +8,8 @@ const blueslip = require("../zjsunit/zblueslip");
const $ = require("../zjsunit/zjquery"); const $ = require("../zjsunit/zjquery");
const {page_params, user_settings} = require("../zjsunit/zpage_params"); const {page_params, user_settings} = require("../zjsunit/zpage_params");
const window_stub = $.create("window-stub"); const $window_stub = $.create("window-stub");
set_global("to_$", () => window_stub); set_global("to_$", () => $window_stub);
$(window).idle = () => {}; $(window).idle = () => {};
const _document = { const _document = {
@@ -242,34 +242,34 @@ function simulate_right_column_buddy_list() {
}; };
} }
function buddy_list_add(user_id, stub) { function buddy_list_add(user_id, $stub) {
if (stub.attr) { if ($stub.attr) {
stub.attr("data-user-id", user_id); $stub.attr("data-user-id", user_id);
} }
stub.length = 1; $stub.length = 1;
const sel = `li.user_sidebar_entry[data-user-id='${CSS.escape(user_id)}']`; const sel = `li.user_sidebar_entry[data-user-id='${CSS.escape(user_id)}']`;
$("#user_presences").set_find_results(sel, stub); $("#user_presences").set_find_results(sel, $stub);
} }
test("PM_update_dom_counts", () => { test("PM_update_dom_counts", () => {
const count = $.create("alice-unread-count"); const $count = $.create("alice-unread-count");
const pm_key = alice.user_id.toString(); const pm_key = alice.user_id.toString();
const li = $.create("alice stub"); const $li = $.create("alice stub");
buddy_list_add(pm_key, li); buddy_list_add(pm_key, $li);
li.set_find_results(".unread_count", count); $li.set_find_results(".unread_count", $count);
count.set_parents_result("li", li); $count.set_parents_result("li", $li);
const counts = new Map(); const counts = new Map();
counts.set(pm_key, 5); counts.set(pm_key, 5);
li.addClass("user_sidebar_entry"); $li.addClass("user_sidebar_entry");
activity.update_dom_with_unread_counts({pm_count: counts}); activity.update_dom_with_unread_counts({pm_count: counts});
assert.equal(count.text(), "5"); assert.equal($count.text(), "5");
counts.set(pm_key, 0); counts.set(pm_key, 0);
activity.update_dom_with_unread_counts({pm_count: counts}); activity.update_dom_with_unread_counts({pm_count: counts});
assert.equal(count.text(), ""); assert.equal($count.text(), "");
}); });
test("handlers", ({override, override_rewire, mock_template}) => { test("handlers", ({override, override_rewire, mock_template}) => {
@@ -289,9 +289,9 @@ test("handlers", ({override, override_rewire, mock_template}) => {
// This is kind of weak coverage; we are mostly making sure that // This is kind of weak coverage; we are mostly making sure that
// keys and clicks got mapped to functions that don't crash. // keys and clicks got mapped to functions that don't crash.
let me_li; let $me_li;
let alice_li; let $alice_li;
let fred_li; let $fred_li;
let narrowed; let narrowed;
@@ -307,13 +307,13 @@ test("handlers", ({override, override_rewire, mock_template}) => {
}); });
activity.set_cursor_and_filter(); activity.set_cursor_and_filter();
me_li = $.create("me stub"); $me_li = $.create("me stub");
alice_li = $.create("alice stub"); $alice_li = $.create("alice stub");
fred_li = $.create("fred stub"); $fred_li = $.create("fred stub");
buddy_list_add(me.user_id, me_li); buddy_list_add(me.user_id, $me_li);
buddy_list_add(alice.user_id, alice_li); buddy_list_add(alice.user_id, $alice_li);
buddy_list_add(fred.user_id, fred_li); buddy_list_add(fred.user_id, $fred_li);
} }
(function test_filter_keys() { (function test_filter_keys() {
@@ -364,7 +364,7 @@ test("handlers", ({override, override_rewire, mock_template}) => {
// We wire up the click handler in click_handlers.js, // We wire up the click handler in click_handlers.js,
// so this just tests the called function. // so this just tests the called function.
narrowed = false; narrowed = false;
activity.narrow_for_user({li: alice_li}); activity.narrow_for_user({$li: $alice_li});
assert.ok(narrowed); assert.ok(narrowed);
})(); })();
@@ -420,7 +420,7 @@ test("first/prev/next", ({override, mock_template}) => {
assert.equal(buddy_list.prev_key(alice.user_id), undefined); assert.equal(buddy_list.prev_key(alice.user_id), undefined);
assert.equal(buddy_list.next_key(alice.user_id), undefined); assert.equal(buddy_list.next_key(alice.user_id), undefined);
override(buddy_list.container, "append", () => {}); override(buddy_list.$container, "append", () => {});
activity.redraw_user(alice.user_id); activity.redraw_user(alice.user_id);
activity.redraw_user(fred.user_id); activity.redraw_user(fred.user_id);
@@ -457,7 +457,7 @@ test("insert_one_user_into_empty_list", ({override, mock_template}) => {
override(padded_widget, "update_padding", () => {}); override(padded_widget, "update_padding", () => {});
let appended_html; let appended_html;
override(buddy_list.container, "append", (html) => { override(buddy_list.$container, "append", (html) => {
appended_html = html; appended_html = html;
}); });
@@ -470,7 +470,7 @@ test("insert_alice_then_fred", ({override, mock_template}) => {
mock_template("user_presence_row.hbs", true, (data, html) => html); mock_template("user_presence_row.hbs", true, (data, html) => html);
let appended_html; let appended_html;
override(buddy_list.container, "append", (html) => { override(buddy_list.$container, "append", (html) => {
appended_html = html; appended_html = html;
}); });
override(padded_widget, "update_padding", () => {}); override(padded_widget, "update_padding", () => {});
@@ -488,7 +488,7 @@ test("insert_fred_then_alice_then_rename", ({override, mock_template}) => {
mock_template("user_presence_row.hbs", true, (data, html) => html); mock_template("user_presence_row.hbs", true, (data, html) => html);
let appended_html; let appended_html;
override(buddy_list.container, "append", (html) => { override(buddy_list.$container, "append", (html) => {
appended_html = html; appended_html = html;
}); });
override(padded_widget, "update_padding", () => {}); override(padded_widget, "update_padding", () => {});
@@ -497,16 +497,16 @@ test("insert_fred_then_alice_then_rename", ({override, mock_template}) => {
assert.ok(appended_html.indexOf('data-user-id="2"') > 0); assert.ok(appended_html.indexOf('data-user-id="2"') > 0);
assert.ok(appended_html.indexOf("user_circle_green") > 0); assert.ok(appended_html.indexOf("user_circle_green") > 0);
const fred_stub = $.create("fred-first"); const $fred_stub = $.create("fred-first");
buddy_list_add(fred.user_id, fred_stub); buddy_list_add(fred.user_id, $fred_stub);
let inserted_html; let inserted_html;
fred_stub.before = (html) => { $fred_stub.before = (html) => {
inserted_html = html; inserted_html = html;
}; };
let fred_removed; let fred_removed;
fred_stub.remove = () => { $fred_stub.remove = () => {
fred_removed = true; fred_removed = true;
}; };
@@ -522,10 +522,10 @@ test("insert_fred_then_alice_then_rename", ({override, mock_template}) => {
}; };
people.add_active_user(fred_with_new_name); people.add_active_user(fred_with_new_name);
const alice_stub = $.create("alice-first"); const $alice_stub = $.create("alice-first");
buddy_list_add(alice.user_id, alice_stub); buddy_list_add(alice.user_id, $alice_stub);
alice_stub.before = (html) => { $alice_stub.before = (html) => {
inserted_html = html; inserted_html = html;
}; };
@@ -541,8 +541,8 @@ test("insert_unfiltered_user_with_filter", () => {
// This test only tests that we do not explode when // This test only tests that we do not explode when
// try to insert Fred into a list where he does not // try to insert Fred into a list where he does not
// match the search filter. // match the search filter.
const user_filter = $(".user-list-filter"); const $user_filter = $(".user-list-filter");
user_filter.val("do-not-match-filter"); $user_filter.val("do-not-match-filter");
activity.redraw_user(fred.user_id); activity.redraw_user(fred.user_id);
}); });
@@ -579,8 +579,8 @@ test("update_presence_info", ({override, override_rewire}) => {
override_rewire(buddy_data, "matches_filter", () => true); override_rewire(buddy_data, "matches_filter", () => true);
const alice_li = $.create("alice stub"); const $alice_li = $.create("alice stub");
buddy_list_add(alice.user_id, alice_li); buddy_list_add(alice.user_id, $alice_li);
let inserted; let inserted;
override(buddy_list, "insert_or_move", () => { override(buddy_list, "insert_or_move", () => {
@@ -613,8 +613,8 @@ test("initialize", ({override, mock_template}) => {
function clear() { function clear() {
$.clear_all_elements(); $.clear_all_elements();
buddy_list.container = $("#user_presences"); buddy_list.$container = $("#user_presences");
buddy_list.container.append = () => {}; buddy_list.$container.append = () => {};
clear_buddy_list(); clear_buddy_list();
page_params.presences = {}; page_params.presences = {};
} }

View File

@@ -50,31 +50,31 @@ run_test("add_alert_word", ({override_rewire}) => {
alert_words_ui.set_up_alert_words(); alert_words_ui.set_up_alert_words();
const create_form = $("#create_alert_word_form"); const $create_form = $("#create_alert_word_form");
const add_func = create_form.get_on_handler("click", "#create_alert_word_button"); const add_func = $create_form.get_on_handler("click", "#create_alert_word_button");
const new_alert_word = $("#create_alert_word_name"); const $new_alert_word = $("#create_alert_word_name");
const alert_word_status = $("#alert_word_status"); const $alert_word_status = $("#alert_word_status");
const alert_word_status_text = $(".alert_word_status_text"); const $alert_word_status_text = $(".alert_word_status_text");
alert_word_status.set_find_results(".alert_word_status_text", alert_word_status_text); $alert_word_status.set_find_results(".alert_word_status_text", $alert_word_status_text);
// add '' as alert word // add '' as alert word
add_func(); add_func();
assert.equal(new_alert_word.val(), ""); assert.equal($new_alert_word.val(), "");
assert.ok(alert_word_status.hasClass("alert-danger")); assert.ok($alert_word_status.hasClass("alert-danger"));
assert.equal(alert_word_status_text.text(), "translated: Alert word can't be empty!"); assert.equal($alert_word_status_text.text(), "translated: Alert word can't be empty!");
assert.ok(alert_word_status.visible()); assert.ok($alert_word_status.visible());
// add 'foo' as alert word (existing word) // add 'foo' as alert word (existing word)
new_alert_word.val("foo"); $new_alert_word.val("foo");
add_func(); add_func();
assert.ok(alert_word_status.hasClass("alert-danger")); assert.ok($alert_word_status.hasClass("alert-danger"));
assert.equal(alert_word_status_text.text(), "translated: Alert word already exists!"); assert.equal($alert_word_status_text.text(), "translated: Alert word already exists!");
assert.ok(alert_word_status.visible()); assert.ok($alert_word_status.visible());
// add 'zot' as alert word (new word) // add 'zot' as alert word (new word)
new_alert_word.val("zot"); $new_alert_word.val("zot");
let success_func; let success_func;
let fail_func; let fail_func;
@@ -89,26 +89,29 @@ run_test("add_alert_word", ({override_rewire}) => {
// test failure // test failure
fail_func(); fail_func();
assert.ok(alert_word_status.hasClass("alert-danger")); assert.ok($alert_word_status.hasClass("alert-danger"));
assert.equal(alert_word_status_text.text(), "translated: Error adding alert word!"); assert.equal($alert_word_status_text.text(), "translated: Error adding alert word!");
assert.ok(alert_word_status.visible()); assert.ok($alert_word_status.visible());
// test success // test success
success_func(); success_func();
assert.ok(alert_word_status.hasClass("alert-success")); assert.ok($alert_word_status.hasClass("alert-success"));
assert.equal(alert_word_status_text.text(), 'translated: Alert word "zot" added successfully!'); assert.equal(
assert.ok(alert_word_status.visible()); $alert_word_status_text.text(),
'translated: Alert word "zot" added successfully!',
);
assert.ok($alert_word_status.visible());
}); });
run_test("add_alert_word_keypress", ({override_rewire}) => { run_test("add_alert_word_keypress", ({override_rewire}) => {
override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {}); override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {});
alert_words_ui.set_up_alert_words(); alert_words_ui.set_up_alert_words();
const create_form = $("#create_alert_word_form"); const $create_form = $("#create_alert_word_form");
const keypress_func = create_form.get_on_handler("keypress", "#create_alert_word_name"); const keypress_func = $create_form.get_on_handler("keypress", "#create_alert_word_name");
const new_alert_word = $("#create_alert_word_name"); const $new_alert_word = $("#create_alert_word_name");
new_alert_word.val("zot"); $new_alert_word.val("zot");
const event = { const event = {
preventDefault: () => {}, preventDefault: () => {},
@@ -130,16 +133,16 @@ run_test("remove_alert_word", ({override_rewire}) => {
override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {}); override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {});
alert_words_ui.set_up_alert_words(); alert_words_ui.set_up_alert_words();
const word_list = $("#alert-words-table"); const $word_list = $("#alert-words-table");
const remove_func = word_list.get_on_handler("click", ".remove-alert-word"); const remove_func = $word_list.get_on_handler("click", ".remove-alert-word");
const remove_alert_word = $(".remove-alert-word"); const $remove_alert_word = $(".remove-alert-word");
const list_item = $("tr.alert-word-item"); const $list_item = $("tr.alert-word-item");
const val_item = $("span.value"); const $val_item = $("span.value");
val_item.text($t({defaultMessage: "zot"})); $val_item.text($t({defaultMessage: "zot"}));
remove_alert_word.set_parents_result("tr", list_item); $remove_alert_word.set_parents_result("tr", $list_item);
list_item.set_find_results(".value", val_item); $list_item.set_find_results(".value", $val_item);
const event = { const event = {
currentTarget: ".remove-alert-word", currentTarget: ".remove-alert-word",
@@ -156,42 +159,42 @@ run_test("remove_alert_word", ({override_rewire}) => {
remove_func(event); remove_func(event);
const alert_word_status = $("#alert_word_status"); const $alert_word_status = $("#alert_word_status");
const alert_word_status_text = $(".alert_word_status_text"); const $alert_word_status_text = $(".alert_word_status_text");
alert_word_status.set_find_results(".alert_word_status_text", alert_word_status_text); $alert_word_status.set_find_results(".alert_word_status_text", $alert_word_status_text);
// test failure // test failure
fail_func(); fail_func();
assert.ok(alert_word_status.hasClass("alert-danger")); assert.ok($alert_word_status.hasClass("alert-danger"));
assert.equal(alert_word_status_text.text(), "translated: Error removing alert word!"); assert.equal($alert_word_status_text.text(), "translated: Error removing alert word!");
assert.ok(alert_word_status.visible()); assert.ok($alert_word_status.visible());
// test success // test success
success_func(); success_func();
assert.ok(alert_word_status.hasClass("alert-success")); assert.ok($alert_word_status.hasClass("alert-success"));
assert.equal(alert_word_status_text.text(), "translated: Alert word removed successfully!"); assert.equal($alert_word_status_text.text(), "translated: Alert word removed successfully!");
assert.ok(alert_word_status.visible()); assert.ok($alert_word_status.visible());
}); });
run_test("close_status_message", ({override_rewire}) => { run_test("close_status_message", ({override_rewire}) => {
override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {}); override_rewire(alert_words_ui, "rerender_alert_words_ui", () => {});
alert_words_ui.set_up_alert_words(); alert_words_ui.set_up_alert_words();
const alert_word_settings = $("#alert-word-settings"); const $alert_word_settings = $("#alert-word-settings");
const close = alert_word_settings.get_on_handler("click", ".close-alert-word-status"); const close = $alert_word_settings.get_on_handler("click", ".close-alert-word-status");
const alert = $(".alert"); const $alert = $(".alert");
const close_btn = $(".close-alert-word-status"); const $close_btn = $(".close-alert-word-status");
close_btn.set_parents_result(".alert", alert); $close_btn.set_parents_result(".alert", $alert);
alert.show(); $alert.show();
const event = { const event = {
preventDefault: () => {}, preventDefault: () => {},
currentTarget: ".close-alert-word-status", currentTarget: ".close-alert-word-status",
}; };
assert.ok(alert.visible()); assert.ok($alert.visible());
close(event); close(event);
assert.ok(!alert.visible()); assert.ok(!$alert.visible());
}); });

View File

@@ -39,18 +39,18 @@ people.add_active_user(alice);
run_test("get_items", () => { run_test("get_items", () => {
const buddy_list = new BuddyList(); const buddy_list = new BuddyList();
// We don't make alice_li an actual jQuery stub, // We don't make $alice_li an actual jQuery stub,
// because our test only cares that it comes // because our test only cares that it comes
// back from get_items. // back from get_items.
const alice_li = "alice stub"; const $alice_li = "alice stub";
const sel = "li.user_sidebar_entry"; const sel = "li.user_sidebar_entry";
const container = $.create("get_items container", { const $container = $.create("get_items container", {
children: [{to_$: () => alice_li}], children: [{to_$: () => $alice_li}],
}); });
buddy_list.container.set_find_results(sel, container); buddy_list.$container.set_find_results(sel, $container);
const items = buddy_list.get_items(); const items = buddy_list.get_items();
assert.deepEqual(items, [alice_li]); assert.deepEqual(items, [$alice_li]);
}); });
run_test("basics", ({override}) => { run_test("basics", ({override}) => {
@@ -83,19 +83,19 @@ run_test("basics", ({override}) => {
}); });
assert.ok(appended); assert.ok(appended);
const alice_li = {length: 1}; const $alice_li = {length: 1};
override(buddy_list, "get_li_from_key", (opts) => { override(buddy_list, "get_li_from_key", (opts) => {
const key = opts.key; const key = opts.key;
assert.equal(key, alice.user_id); assert.equal(key, alice.user_id);
return alice_li; return $alice_li;
}); });
const li = buddy_list.find_li({ const $li = buddy_list.find_li({
key: alice.user_id, key: alice.user_id,
}); });
assert.equal(li, alice_li); assert.equal($li, $alice_li);
}); });
run_test("big_list", ({override}) => { run_test("big_list", ({override}) => {
@@ -163,11 +163,11 @@ run_test("find_li w/force_render", ({override}) => {
// key is not already rendered in DOM, then the // key is not already rendered in DOM, then the
// widget will call show_key to force-render it. // widget will call show_key to force-render it.
const key = "999"; const key = "999";
const stub_li = {length: 0}; const $stub_li = {length: 0};
override(buddy_list, "get_li_from_key", (opts) => { override(buddy_list, "get_li_from_key", (opts) => {
assert.equal(opts.key, key); assert.equal(opts.key, key);
return stub_li; return $stub_li;
}); });
buddy_list.keys = ["foo", "bar", key, "baz"]; buddy_list.keys = ["foo", "bar", key, "baz"];
@@ -179,18 +179,18 @@ run_test("find_li w/force_render", ({override}) => {
shown = true; shown = true;
}); });
const empty_li = buddy_list.find_li({ const $empty_li = buddy_list.find_li({
key, key,
}); });
assert.equal(empty_li, stub_li); assert.equal($empty_li, $stub_li);
assert.ok(!shown); assert.ok(!shown);
const li = buddy_list.find_li({ const $li = buddy_list.find_li({
key, key,
force_render: true, force_render: true,
}); });
assert.equal(li, stub_li); assert.equal($li, $stub_li);
assert.ok(shown); assert.ok(shown);
}); });
@@ -198,12 +198,12 @@ run_test("find_li w/bad key", ({override}) => {
const buddy_list = new BuddyList(); const buddy_list = new BuddyList();
override(buddy_list, "get_li_from_key", () => ({length: 0})); override(buddy_list, "get_li_from_key", () => ({length: 0}));
const undefined_li = buddy_list.find_li({ const $undefined_li = buddy_list.find_li({
key: "not-there", key: "not-there",
force_render: true, force_render: true,
}); });
assert.deepEqual(undefined_li, []); assert.deepEqual($undefined_li, []);
}); });
run_test("scrolling", ({override}) => { run_test("scrolling", ({override}) => {

View File

@@ -39,41 +39,41 @@ run_test("phrase_match", () => {
run_test("copy_data_attribute_value", ({override}) => { run_test("copy_data_attribute_value", ({override}) => {
const admin_emails_val = "iago@zulip.com"; const admin_emails_val = "iago@zulip.com";
const input = $.create("input"); const $input = $.create("input");
let removed; let removed;
input.remove = () => { $input.remove = () => {
removed = true; removed = true;
}; };
override(document, "createElement", () => input); override(document, "createElement", () => $input);
override(document, "execCommand", noop); override(document, "execCommand", noop);
$("body").append = noop; $("body").append = noop;
$(input).val = (arg) => { $($input).val = (arg) => {
assert.equal(arg, admin_emails_val); assert.equal(arg, admin_emails_val);
return { return {
trigger: noop, trigger: noop,
}; };
}; };
const elem = {}; const $elem = {};
let faded_in = false; let faded_in = false;
let faded_out = false; let faded_out = false;
elem.data = (key) => { $elem.data = (key) => {
assert.equal(key, "admin-emails"); assert.equal(key, "admin-emails");
return admin_emails_val; return admin_emails_val;
}; };
elem.fadeOut = (val) => { $elem.fadeOut = (val) => {
assert.equal(val, 250); assert.equal(val, 250);
faded_out = true; faded_out = true;
}; };
elem.fadeIn = (val) => { $elem.fadeIn = (val) => {
assert.equal(val, 1000); assert.equal(val, 1000);
faded_in = true; faded_in = true;
}; };
common.copy_data_attribute_value(elem, "admin-emails"); common.copy_data_attribute_value($elem, "admin-emails");
assert.ok(removed); assert.ok(removed);
assert.ok(faded_in); assert.ok(faded_in);
assert.ok(faded_out); assert.ok(faded_out);
@@ -111,17 +111,17 @@ run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
for (const [old_key, mac_key] of keys_to_test_mac) { for (const [old_key, mac_key] of keys_to_test_mac) {
const test_item = {}; const test_item = {};
const stub = $.create("hotkey_" + key_no); const $stub = $.create("hotkey_" + key_no);
stub.text(old_key); $stub.text(old_key);
assert.equal(stub.hasClass("mac-cmd-key"), false); assert.equal($stub.hasClass("mac-cmd-key"), false);
test_item.stub = stub; test_item.$stub = $stub;
test_item.mac_key = mac_key; test_item.mac_key = mac_key;
test_item.is_cmd_key = old_key.includes("Ctrl"); test_item.is_cmd_key = old_key.includes("Ctrl");
test_items.push(test_item); test_items.push(test_item);
key_no += 1; key_no += 1;
} }
const children = test_items.map((test_item) => ({to_$: () => test_item.stub})); const children = test_items.map((test_item) => ({to_$: () => test_item.$stub}));
$.create(".markdown_content", {children}); $.create(".markdown_content", {children});
@@ -129,8 +129,8 @@ run_test("adjust_mac_shortcuts mac", ({override_rewire}) => {
common.adjust_mac_shortcuts(".markdown_content", require_cmd); common.adjust_mac_shortcuts(".markdown_content", require_cmd);
for (const test_item of test_items) { for (const test_item of test_items) {
assert.equal(test_item.stub.hasClass("mac-cmd-key"), test_item.is_cmd_key); assert.equal(test_item.$stub.hasClass("mac-cmd-key"), test_item.is_cmd_key);
assert.equal(test_item.stub.text(), test_item.mac_key); assert.equal(test_item.$stub.text(), test_item.mac_key);
} }
}); });

View File

@@ -10,35 +10,35 @@ const blueslip = require("../zjsunit/zblueslip");
let env; let env;
function make_tab(i) { function make_tab(i) {
const self = {}; const $self = {};
assert.equal(env.tabs.length, i); assert.equal(env.tabs.length, i);
self.stub = true; $self.stub = true;
self.class = []; $self.class = [];
self.addClass = (c) => { $self.addClass = (c) => {
self.class += " " + c; $self.class += " " + c;
const tokens = self.class.trim().split(/ +/); const tokens = $self.class.trim().split(/ +/);
self.class = Array.from(new Set(tokens)).join(" "); $self.class = Array.from(new Set(tokens)).join(" ");
}; };
self.removeClass = (c) => { $self.removeClass = (c) => {
const tokens = self.class.trim().split(/ +/); const tokens = $self.class.trim().split(/ +/);
self.class = tokens.filter((token) => token !== c).join(" "); $self.class = tokens.filter((token) => token !== c).join(" ");
}; };
self.hasClass = (c) => { $self.hasClass = (c) => {
const tokens = self.class.trim().split(/ +/); const tokens = $self.class.trim().split(/ +/);
return tokens.includes(c); return tokens.includes(c);
}; };
self.data = (name) => { $self.data = (name) => {
assert.equal(name, "tab-id"); assert.equal(name, "tab-id");
return i; return i;
}; };
self.text = (text) => { $self.text = (text) => {
assert.equal( assert.equal(
text, text,
[ [
@@ -49,23 +49,23 @@ function make_tab(i) {
); );
}; };
self.trigger = (type) => { $self.trigger = (type) => {
if (type === "focus") { if (type === "focus") {
env.focused_tab = i; env.focused_tab = i;
} }
}; };
env.tabs.push(self); env.tabs.push($self);
return self; return $self;
} }
const ind_tab = (function () { const ind_tab = (function () {
const self = {}; const $self = {};
self.stub = true; $self.stub = true;
self.on = (name, f) => { $self.on = (name, f) => {
if (name === "click") { if (name === "click") {
env.click_f = f; env.click_f = f;
} else if (name === "keydown") { } else if (name === "keydown") {
@@ -73,36 +73,36 @@ const ind_tab = (function () {
} }
}; };
self.removeClass = (c) => { $self.removeClass = (c) => {
for (const tab of env.tabs) { for (const $tab of env.tabs) {
tab.removeClass(c); $tab.removeClass(c);
} }
}; };
self.eq = (idx) => env.tabs[idx]; $self.eq = (idx) => env.tabs[idx];
return self; return $self;
})(); })();
function make_switcher() { function make_switcher() {
const self = {}; const $self = {};
self.stub = true; $self.stub = true;
self.children = []; $self.children = [];
self.classList = new Set(); $self.classList = new Set();
self.append = (child) => { $self.append = (child) => {
self.children.push(child); $self.children.push(child);
}; };
self.addClass = (c) => { $self.addClass = (c) => {
self.classList.add(c); $self.classList.add(c);
self.addedClass = c; $self.addedClass = c;
}; };
self.find = (sel) => { $self.find = (sel) => {
switch (sel) { switch (sel) {
case ".ind-tab": case ".ind-tab":
return ind_tab; return ind_tab;
@@ -111,7 +111,7 @@ function make_switcher() {
} }
}; };
return self; return $self;
} }
mock_jquery((sel, attributes) => { mock_jquery((sel, attributes) => {

View File

@@ -552,27 +552,28 @@ test_ui("on_events", ({override, override_rewire}) => {
override(rendered_markdown, "update_elements", () => {}); override(rendered_markdown, "update_elements", () => {});
function setup_parents_and_mock_remove(container_sel, target_sel, parent) { function setup_parents_and_mock_remove(container_sel, target_sel, parent) {
const container = $.create("fake " + container_sel); const $container = $.create("fake " + container_sel);
let container_removed = false; let container_removed = false;
container.remove = () => { $container.remove = () => {
container_removed = true; container_removed = true;
}; };
const target = $.create("fake click target (" + target_sel + ")"); const $target = $.create("fake click target (" + target_sel + ")");
target.set_parents_result(parent, container); $target.set_parents_result(parent, $container);
const event = { const event = {
preventDefault: noop, preventDefault: noop,
stopPropagation: noop, stopPropagation: noop,
target, // FIXME: event.target should not be a jQuery object
target: $target,
}; };
const helper = { const helper = {
event, event,
container, $container,
target, $target,
container_was_removed: () => container_removed, container_was_removed: () => container_removed,
}; };
@@ -633,7 +634,7 @@ test_ui("on_events", ({override, override_rewire}) => {
".compose_invite_user", ".compose_invite_user",
); );
helper.container.data = (field) => { helper.$container.data = (field) => {
if (field === "user-id") { if (field === "user-id") {
return "34"; return "34";
} }
@@ -642,7 +643,7 @@ test_ui("on_events", ({override, override_rewire}) => {
} }
throw new Error(`Unknown field ${field}`); throw new Error(`Unknown field ${field}`);
}; };
helper.target.prop("disabled", false); helper.$target.prop("disabled", false);
// !sub will result in true here and we check the success code path. // !sub will result in true here and we check the success code path.
stream_data.add_sub(subscription); stream_data.add_sub(subscription);

View File

@@ -43,9 +43,9 @@ run_test("pills", ({override}) => {
people.get_realm_users = () => [iago, othello, hamlet]; people.get_realm_users = () => [iago, othello, hamlet];
const recipient_stub = $("#private_message_recipient"); const $recipient_stub = $("#private_message_recipient");
const pill_container_stub = "pill-container"; const pill_container_stub = "pill-container";
recipient_stub.set_parent(pill_container_stub); $recipient_stub.set_parent(pill_container_stub);
let create_item_handler; let create_item_handler;
const all_pills = new Map(); const all_pills = new Map();
@@ -132,7 +132,7 @@ run_test("pills", ({override}) => {
} }
function input_pill_stub(opts) { function input_pill_stub(opts) {
assert.equal(opts.container, pill_container_stub); assert.equal(opts.$container, pill_container_stub);
create_item_handler = opts.create_item_from_text; create_item_handler = opts.create_item_from_text;
assert.ok(create_item_handler); assert.ok(create_item_handler);
return pills; return pills;

View File

@@ -46,48 +46,48 @@ people.add_active_user(bob);
function make_textbox(s) { function make_textbox(s) {
// Simulate a jQuery textbox for testing purposes. // Simulate a jQuery textbox for testing purposes.
const widget = {}; const $widget = {};
widget.s = s; $widget.s = s;
widget.focused = false; $widget.focused = false;
widget.caret = function (arg) { $widget.caret = function (arg) {
if (typeof arg === "number") { if (typeof arg === "number") {
widget.pos = arg; $widget.pos = arg;
return this; return this;
} }
if (arg) { if (arg) {
widget.insert_pos = widget.pos; $widget.insert_pos = $widget.pos;
widget.insert_text = arg; $widget.insert_text = arg;
const before = widget.s.slice(0, widget.pos); const before = $widget.s.slice(0, $widget.pos);
const after = widget.s.slice(widget.pos); const after = $widget.s.slice($widget.pos);
widget.s = before + arg + after; $widget.s = before + arg + after;
widget.pos += arg.length; $widget.pos += arg.length;
return this; return this;
} }
return widget.pos; return $widget.pos;
}; };
widget.val = function (new_val) { $widget.val = function (new_val) {
if (new_val) { if (new_val) {
widget.s = new_val; $widget.s = new_val;
return this; return this;
} }
return widget.s; return $widget.s;
}; };
widget.trigger = function (type) { $widget.trigger = function (type) {
if (type === "focus") { if (type === "focus") {
widget.focused = true; $widget.focused = true;
} else if (type === "blur") { } else if (type === "blur") {
widget.focused = false; $widget.focused = false;
} }
return this; return this;
}; };
return widget; return $widget;
} }
run_test("autosize_textarea", ({override}) => { run_test("autosize_textarea", ({override}) => {
@@ -121,59 +121,59 @@ run_test("insert_syntax_and_focus", () => {
}); });
run_test("smart_insert", () => { run_test("smart_insert", () => {
let textbox = make_textbox("abc"); let $textbox = make_textbox("abc");
textbox.caret(4); $textbox.caret(4);
compose_ui.smart_insert(textbox, ":smile:"); compose_ui.smart_insert($textbox, ":smile:");
assert.equal(textbox.insert_pos, 4); assert.equal($textbox.insert_pos, 4);
assert.equal(textbox.insert_text, " :smile: "); assert.equal($textbox.insert_text, " :smile: ");
assert.equal(textbox.val(), "abc :smile: "); assert.equal($textbox.val(), "abc :smile: ");
assert.ok(textbox.focused); assert.ok($textbox.focused);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, ":airplane:"); compose_ui.smart_insert($textbox, ":airplane:");
assert.equal(textbox.insert_text, ":airplane: "); assert.equal($textbox.insert_text, ":airplane: ");
assert.equal(textbox.val(), "abc :smile: :airplane: "); assert.equal($textbox.val(), "abc :smile: :airplane: ");
assert.ok(textbox.focused); assert.ok($textbox.focused);
textbox.caret(0); $textbox.caret(0);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, ":octopus:"); compose_ui.smart_insert($textbox, ":octopus:");
assert.equal(textbox.insert_text, ":octopus: "); assert.equal($textbox.insert_text, ":octopus: ");
assert.equal(textbox.val(), ":octopus: abc :smile: :airplane: "); assert.equal($textbox.val(), ":octopus: abc :smile: :airplane: ");
assert.ok(textbox.focused); assert.ok($textbox.focused);
textbox.caret(textbox.val().length); $textbox.caret($textbox.val().length);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, ":heart:"); compose_ui.smart_insert($textbox, ":heart:");
assert.equal(textbox.insert_text, ":heart: "); assert.equal($textbox.insert_text, ":heart: ");
assert.equal(textbox.val(), ":octopus: abc :smile: :airplane: :heart: "); assert.equal($textbox.val(), ":octopus: abc :smile: :airplane: :heart: ");
assert.ok(textbox.focused); assert.ok($textbox.focused);
// Test handling of spaces for ```quote // Test handling of spaces for ```quote
textbox = make_textbox(""); $textbox = make_textbox("");
textbox.caret(0); $textbox.caret(0);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, "```quote\nquoted message\n```\n"); compose_ui.smart_insert($textbox, "```quote\nquoted message\n```\n");
assert.equal(textbox.insert_text, "```quote\nquoted message\n```\n"); assert.equal($textbox.insert_text, "```quote\nquoted message\n```\n");
assert.equal(textbox.val(), "```quote\nquoted message\n```\n"); assert.equal($textbox.val(), "```quote\nquoted message\n```\n");
assert.ok(textbox.focused); assert.ok($textbox.focused);
textbox = make_textbox(""); $textbox = make_textbox("");
textbox.caret(0); $textbox.caret(0);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, "translated: [Quoting…]\n"); compose_ui.smart_insert($textbox, "translated: [Quoting…]\n");
assert.equal(textbox.insert_text, "translated: [Quoting…]\n"); assert.equal($textbox.insert_text, "translated: [Quoting…]\n");
assert.equal(textbox.val(), "translated: [Quoting…]\n"); assert.equal($textbox.val(), "translated: [Quoting…]\n");
assert.ok(textbox.focused); assert.ok($textbox.focused);
textbox = make_textbox("abc"); $textbox = make_textbox("abc");
textbox.caret(3); $textbox.caret(3);
textbox.trigger("blur"); $textbox.trigger("blur");
compose_ui.smart_insert(textbox, " test with space"); compose_ui.smart_insert($textbox, " test with space");
assert.equal(textbox.insert_text, " test with space "); assert.equal($textbox.insert_text, " test with space ");
assert.equal(textbox.val(), "abc test with space "); assert.equal($textbox.val(), "abc test with space ");
assert.ok(textbox.focused); assert.ok($textbox.focused);
// Note that we don't have any special logic for strings that are // Note that we don't have any special logic for strings that are
// already surrounded by spaces, since we are usually inserting things // already surrounded by spaces, since we are usually inserting things
@@ -481,14 +481,14 @@ run_test("format_text", () => {
wrap_syntax = ""; wrap_syntax = "";
} }
const textarea = $("#compose-textarea"); const $textarea = $("#compose-textarea");
textarea.get = () => ({ $textarea.get = () => ({
setSelectionRange: () => {}, setSelectionRange: () => {},
}); });
function init_textarea(val, range) { function init_textarea(val, range) {
textarea.val = () => val; $textarea.val = () => val;
textarea.range = () => range; $textarea.range = () => range;
} }
const italic_syntax = "*"; const italic_syntax = "*";
@@ -502,7 +502,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 3, length: 3,
}); });
compose_ui.format_text(textarea, "bold"); compose_ui.format_text($textarea, "bold");
assert.equal(set_text, ""); assert.equal(set_text, "");
assert.equal(wrap_selection_called, true); assert.equal(wrap_selection_called, true);
assert.equal(wrap_syntax, bold_syntax); assert.equal(wrap_syntax, bold_syntax);
@@ -515,7 +515,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 7, length: 7,
}); });
compose_ui.format_text(textarea, "bold"); compose_ui.format_text($textarea, "bold");
assert.equal(set_text, "abc"); assert.equal(set_text, "abc");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -527,7 +527,7 @@ run_test("format_text", () => {
text: "**abc**", text: "**abc**",
length: 7, length: 7,
}); });
compose_ui.format_text(textarea, "bold"); compose_ui.format_text($textarea, "bold");
assert.equal(set_text, "abc"); assert.equal(set_text, "abc");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -539,7 +539,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 3, length: 3,
}); });
compose_ui.format_text(textarea, "italic"); compose_ui.format_text($textarea, "italic");
assert.equal(set_text, ""); assert.equal(set_text, "");
assert.equal(wrap_selection_called, true); assert.equal(wrap_selection_called, true);
assert.equal(wrap_syntax, italic_syntax); assert.equal(wrap_syntax, italic_syntax);
@@ -552,7 +552,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 3, length: 3,
}); });
compose_ui.format_text(textarea, "italic"); compose_ui.format_text($textarea, "italic");
assert.equal(set_text, "abc"); assert.equal(set_text, "abc");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -564,7 +564,7 @@ run_test("format_text", () => {
text: "*abc*", text: "*abc*",
length: 5, length: 5,
}); });
compose_ui.format_text(textarea, "italic"); compose_ui.format_text($textarea, "italic");
assert.equal(set_text, "abc"); assert.equal(set_text, "abc");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -576,7 +576,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 3, length: 3,
}); });
compose_ui.format_text(textarea, "bold"); compose_ui.format_text($textarea, "bold");
assert.equal(set_text, "*abc*"); assert.equal(set_text, "*abc*");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -588,7 +588,7 @@ run_test("format_text", () => {
text: "***abc***", text: "***abc***",
length: 9, length: 9,
}); });
compose_ui.format_text(textarea, "bold"); compose_ui.format_text($textarea, "bold");
assert.equal(set_text, "*abc*"); assert.equal(set_text, "*abc*");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -600,7 +600,7 @@ run_test("format_text", () => {
text: "abc", text: "abc",
length: 3, length: 3,
}); });
compose_ui.format_text(textarea, "italic"); compose_ui.format_text($textarea, "italic");
assert.equal(set_text, "**abc**"); assert.equal(set_text, "**abc**");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
@@ -612,14 +612,14 @@ run_test("format_text", () => {
text: "***abc***", text: "***abc***",
length: 9, length: 9,
}); });
compose_ui.format_text(textarea, "italic"); compose_ui.format_text($textarea, "italic");
assert.equal(set_text, "**abc**"); assert.equal(set_text, "**abc**");
assert.equal(wrap_selection_called, false); assert.equal(wrap_selection_called, false);
}); });
run_test("markdown_shortcuts", ({override_rewire}) => { run_test("markdown_shortcuts", ({override_rewire}) => {
let format_text_type; let format_text_type;
override_rewire(compose_ui, "format_text", (textarea, type) => { override_rewire(compose_ui, "format_text", ($textarea, type) => {
format_text_type = type; format_text_type = type;
}); });
@@ -711,21 +711,21 @@ run_test("markdown_shortcuts", ({override_rewire}) => {
}); });
run_test("right-to-left", () => { run_test("right-to-left", () => {
const textarea = $("#compose-textarea"); const $textarea = $("#compose-textarea");
const event = { const event = {
key: "A", key: "A",
}; };
assert.equal(textarea.hasClass("rtl"), false); assert.equal($textarea.hasClass("rtl"), false);
textarea.val("```quote\nمرحبا"); $textarea.val("```quote\nمرحبا");
compose_ui.handle_keyup(event, $("#compose-textarea")); compose_ui.handle_keyup(event, $("#compose-textarea"));
assert.equal(textarea.hasClass("rtl"), true); assert.equal($textarea.hasClass("rtl"), true);
textarea.val("```quote foo"); $textarea.val("```quote foo");
compose_ui.handle_keyup(event, textarea); compose_ui.handle_keyup(event, $textarea);
assert.equal(textarea.hasClass("rtl"), false); assert.equal($textarea.hasClass("rtl"), false);
}); });

View File

@@ -131,10 +131,10 @@ test_ui("validate", ({override, mock_template}) => {
$("#compose-send-button").trigger("focus"); $("#compose-send-button").trigger("focus");
$("#compose-send-button .loader").hide(); $("#compose-send-button .loader").hide();
const pm_pill_container = $.create("fake-pm-pill-container"); const $pm_pill_container = $.create("fake-pm-pill-container");
$("#private_message_recipient")[0] = {}; $("#private_message_recipient")[0] = {};
$("#private_message_recipient").set_parent(pm_pill_container); $("#private_message_recipient").set_parent($pm_pill_container);
pm_pill_container.set_find_results(".input", $("#private_message_recipient")); $pm_pill_container.set_find_results(".input", $("#private_message_recipient"));
$("#private_message_recipient").before = () => {}; $("#private_message_recipient").before = () => {};
compose_pm_pill.initialize(); compose_pm_pill.initialize();
@@ -474,38 +474,38 @@ test_ui("test_validate_stream_message_post_policy_full_members_only", () => {
test_ui("test_check_overflow_text", () => { test_ui("test_check_overflow_text", () => {
page_params.max_message_length = 10000; page_params.max_message_length = 10000;
const textarea = $("#compose-textarea"); const $textarea = $("#compose-textarea");
const indicator = $("#compose_limit_indicator"); const $indicator = $("#compose_limit_indicator");
const send_button = $("#compose-send-button"); const $send_button = $("#compose-send-button");
// Indicator should show red colored text // Indicator should show red colored text
textarea.val("a".repeat(10000 + 1)); $textarea.val("a".repeat(10000 + 1));
compose_validate.check_overflow_text(); compose_validate.check_overflow_text();
assert.ok(indicator.hasClass("over_limit")); assert.ok($indicator.hasClass("over_limit"));
assert.equal(indicator.text(), "10001/10000"); assert.equal($indicator.text(), "10001/10000");
assert.ok(textarea.hasClass("over_limit")); assert.ok($textarea.hasClass("over_limit"));
assert.equal( assert.equal(
$("#compose-error-msg").html(), $("#compose-error-msg").html(),
"translated HTML: Message length shouldn't be greater than 10000 characters.", "translated HTML: Message length shouldn't be greater than 10000 characters.",
); );
assert.ok(send_button.prop("disabled")); assert.ok($send_button.prop("disabled"));
$("#compose-send-status").stop = () => ({fadeOut: () => {}}); $("#compose-send-status").stop = () => ({fadeOut: () => {}});
// Indicator should show orange colored text // Indicator should show orange colored text
textarea.val("a".repeat(9000 + 1)); $textarea.val("a".repeat(9000 + 1));
compose_validate.check_overflow_text(); compose_validate.check_overflow_text();
assert.ok(!indicator.hasClass("over_limit")); assert.ok(!$indicator.hasClass("over_limit"));
assert.equal(indicator.text(), "9001/10000"); assert.equal($indicator.text(), "9001/10000");
assert.ok(!textarea.hasClass("over_limit")); assert.ok(!$textarea.hasClass("over_limit"));
assert.ok(!send_button.prop("disabled")); assert.ok(!$send_button.prop("disabled"));
// Indicator must be empty // Indicator must be empty
textarea.val("a".repeat(9000)); $textarea.val("a".repeat(9000));
compose_validate.check_overflow_text(); compose_validate.check_overflow_text();
assert.ok(!indicator.hasClass("over_limit")); assert.ok(!$indicator.hasClass("over_limit"));
assert.equal(indicator.text(), ""); assert.equal($indicator.text(), "");
assert.ok(!textarea.hasClass("over_limit")); assert.ok(!$textarea.hasClass("over_limit"));
}); });
test_ui("test_message_overflow", () => { test_ui("test_message_overflow", () => {
@@ -736,10 +736,10 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
} }
// Simulate that the row was added to the DOM. // Simulate that the row was added to the DOM.
const warning_row = $("<warning row>"); const $warning_row = $("<warning row>");
let looked_for_existing; let looked_for_existing;
warning_row.data = (field) => { $warning_row.data = (field) => {
if (field === "user-id") { if (field === "user-id") {
looked_for_existing = true; looked_for_existing = true;
return "34"; return "34";
@@ -750,9 +750,9 @@ test_ui("warn_if_mentioning_unsubscribed_user", ({override, override_rewire, moc
throw new Error(`Unknown field ${field}`); throw new Error(`Unknown field ${field}`);
}; };
const previous_users = $("#compose_invite_users .compose_invite_user"); const $previous_users = $("#compose_invite_users .compose_invite_user");
previous_users.length = 1; $previous_users.length = 1;
previous_users[0] = warning_row; $previous_users[0] = $warning_row;
$("#compose_invite_users").hide(); $("#compose_invite_users").hide();
// Now try to mention the same person again. The template should // Now try to mention the same person again. The template should
@@ -788,12 +788,12 @@ test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
stream_data.add_sub(sub); stream_data.add_sub(sub);
// The error message area where it is shown // The error message area where it is shown
const error_area = $("#compose_resolved_topic"); const $error_area = $("#compose_resolved_topic");
compose_validate.clear_topic_resolved_warning(); compose_validate.clear_topic_resolved_warning();
// Hack to make this empty for zjquery; this is conceptually done // Hack to make this empty for zjquery; this is conceptually done
// in the previous line. // in the previous line.
error_area.html(""); $error_area.html("");
assert.ok(!error_area.visible()); assert.ok(!$error_area.visible());
compose_state.set_message_type("stream"); compose_state.set_message_type("stream");
compose_state.stream_name("Do not exist"); compose_state.stream_name("Do not exist");
@@ -802,25 +802,25 @@ test_ui("test warn_if_topic_resolved", ({override, mock_template}) => {
// Do not show a warning if stream name does not exist // Do not show a warning if stream name does not exist
compose_validate.warn_if_topic_resolved(true); compose_validate.warn_if_topic_resolved(true);
assert.ok(!error_area.visible()); assert.ok(!$error_area.visible());
compose_state.stream_name("random"); compose_state.stream_name("random");
// Show the warning now as stream also exists // Show the warning now as stream also exists
compose_validate.warn_if_topic_resolved(true); compose_validate.warn_if_topic_resolved(true);
assert.ok(error_area.visible()); assert.ok($error_area.visible());
// Call it again with false; this should be a noop. // Call it again with false; this should be a noop.
compose_validate.warn_if_topic_resolved(false); compose_validate.warn_if_topic_resolved(false);
assert.ok(error_area.visible()); assert.ok($error_area.visible());
compose_state.topic("hello"); compose_state.topic("hello");
// The warning will be cleared now // The warning will be cleared now
compose_validate.warn_if_topic_resolved(true); compose_validate.warn_if_topic_resolved(true);
assert.ok(!error_area.visible()); assert.ok(!$error_area.visible());
// Calling with false won't do anything. // Calling with false won't do anything.
compose_validate.warn_if_topic_resolved(false); compose_validate.warn_if_topic_resolved(false);
assert.ok(!error_area.visible()); assert.ok(!$error_area.visible());
}); });

View File

@@ -29,12 +29,12 @@ const server_events_dispatch = zrequire("server_events_dispatch");
const compose_ui = zrequire("compose_ui"); const compose_ui = zrequire("compose_ui");
const compose = zrequire("compose"); const compose = zrequire("compose");
function stub_out_video_calls() { function stub_out_video_calls() {
const elem = $("#below-compose-content .video_link"); const $elem = $("#below-compose-content .video_link");
elem.toggle = (show) => { $elem.toggle = (show) => {
if (show) { if (show) {
elem.show(); $elem.show();
} else { } else {
elem.hide(); $elem.hide();
} }
}; };
} }
@@ -78,14 +78,14 @@ test("videos", ({override, override_rewire}) => {
(function test_no_provider_video_link_compose_clicked() { (function test_no_provider_video_link_compose_clicked() {
let called = false; let called = false;
const textarea = $.create("target-stub"); const $textarea = $.create("target-stub");
textarea.set_parents_result(".message_edit_form", []); $textarea.set_parents_result(".message_edit_form", []);
const ev = { const ev = {
preventDefault: () => {}, preventDefault: () => {},
stopPropagation: () => {}, stopPropagation: () => {},
target: { target: {
to_$: () => textarea, to_$: () => $textarea,
}, },
}; };
@@ -104,14 +104,14 @@ test("videos", ({override, override_rewire}) => {
let syntax_to_insert; let syntax_to_insert;
let called = false; let called = false;
const textarea = $.create("jitsi-target-stub"); const $textarea = $.create("jitsi-target-stub");
textarea.set_parents_result(".message_edit_form", []); $textarea.set_parents_result(".message_edit_form", []);
const ev = { const ev = {
preventDefault: () => {}, preventDefault: () => {},
stopPropagation: () => {}, stopPropagation: () => {},
target: { target: {
to_$: () => textarea, to_$: () => $textarea,
}, },
}; };
@@ -142,14 +142,14 @@ test("videos", ({override, override_rewire}) => {
let syntax_to_insert; let syntax_to_insert;
let called = false; let called = false;
const textarea = $.create("zoom-target-stub"); const $textarea = $.create("zoom-target-stub");
textarea.set_parents_result(".message_edit_form", []); $textarea.set_parents_result(".message_edit_form", []);
const ev = { const ev = {
preventDefault: () => {}, preventDefault: () => {},
stopPropagation: () => {}, stopPropagation: () => {},
target: { target: {
to_$: () => textarea, to_$: () => $textarea,
}, },
}; };
@@ -188,14 +188,14 @@ test("videos", ({override, override_rewire}) => {
let syntax_to_insert; let syntax_to_insert;
let called = false; let called = false;
const textarea = $.create("bbb-target-stub"); const $textarea = $.create("bbb-target-stub");
textarea.set_parents_result(".message_edit_form", []); $textarea.set_parents_result(".message_edit_form", []);
const ev = { const ev = {
preventDefault: () => {}, preventDefault: () => {},
stopPropagation: () => {}, stopPropagation: () => {},
target: { target: {
to_$: () => textarea, to_$: () => $textarea,
}, },
}; };

View File

@@ -120,8 +120,8 @@ test("draft_model add", ({override}) => {
const ls = localstorage(); const ls = localstorage();
assert.equal(ls.get("draft"), undefined); assert.equal(ls.get("draft"), undefined);
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
override(Date, "now", () => 1); override(Date, "now", () => 1);
const expected = {...draft_1}; const expected = {...draft_1};
@@ -136,8 +136,8 @@ test("draft_model edit", () => {
assert.equal(ls.get("draft"), undefined); assert.equal(ls.get("draft"), undefined);
let id; let id;
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
with_overrides(({override}) => { with_overrides(({override}) => {
override(Date, "now", () => 1); override(Date, "now", () => 1);
@@ -161,8 +161,8 @@ test("draft_model delete", ({override}) => {
const ls = localstorage(); const ls = localstorage();
assert.equal(ls.get("draft"), undefined); assert.equal(ls.get("draft"), undefined);
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
override(Date, "now", () => 1); override(Date, "now", () => 1);
const expected = {...draft_1}; const expected = {...draft_1};
@@ -212,8 +212,8 @@ test("initialize", ({override_rewire}) => {
assert.ok(called); assert.ok(called);
}; };
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
drafts.initialize(); drafts.initialize();
}); });
@@ -239,8 +239,8 @@ test("remove_old_drafts", () => {
ls.set("drafts", data); ls.set("drafts", data);
assert.deepEqual(draft_model.get(), data); assert.deepEqual(draft_model.get(), data);
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
drafts.remove_old_drafts(); drafts.remove_old_drafts();
assert.deepEqual(draft_model.get(), {id3: draft_3}); assert.deepEqual(draft_model.get(), {id3: draft_3});
@@ -256,9 +256,9 @@ test("update_draft", ({override}) => {
override(compose_state, "get_message_type", () => "private"); override(compose_state, "get_message_type", () => "private");
override(compose_state, "private_message_recipient", () => "aaron@zulip.com"); override(compose_state, "private_message_recipient", () => "aaron@zulip.com");
const container = $(".top_left_drafts"); const $container = $(".top_left_drafts");
const child = $(".unread_count"); const $child = $(".unread_count");
container.set_find_results(".unread_count", child); $container.set_find_results(".unread_count", $child);
tippy_args = { tippy_args = {
content: "translated: Saved as draft", content: "translated: Saved as draft",
@@ -313,8 +313,8 @@ test("delete_all_drafts", () => {
ls.set("drafts", data); ls.set("drafts", data);
assert.deepEqual(draft_model.get(), data); assert.deepEqual(draft_model.get(), data);
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
drafts.delete_all_drafts(); drafts.delete_all_drafts();
assert.deepEqual(draft_model.get(), {}); assert.deepEqual(draft_model.get(), {});
@@ -451,8 +451,8 @@ test("format_drafts", ({override_rewire, mock_template}) => {
expected[0].stream_name = "stream-rename"; expected[0].stream_name = "stream-rename";
const unread_count = $('<span class="unread_count"></span>'); const $unread_count = $('<span class="unread_count"></span>');
$(".top_left_drafts").set_find_results(".unread_count", unread_count); $(".top_left_drafts").set_find_results(".unread_count", $unread_count);
drafts.launch(); drafts.launch();
timerender.__Rewire__("render_now", stub_render_now); timerender.__Rewire__("render_now", stub_render_now);

View File

@@ -25,12 +25,12 @@ const {DropdownListWidget, MultiSelectDropdownListWidget} = zrequire("dropdown_l
// For DropdownListWidget // For DropdownListWidget
const setup_dropdown_zjquery_data = (name) => { const setup_dropdown_zjquery_data = (name) => {
const input_group = $(".input_group"); const $input_group = $(".input_group");
const reset_button = $(".dropdown_list_reset_button"); const $reset_button = $(".dropdown_list_reset_button");
input_group.set_find_results(".dropdown_list_reset_button", reset_button); $input_group.set_find_results(".dropdown_list_reset_button", $reset_button);
$(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`).closest = () => input_group; $(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`).closest = () => $input_group;
const $widget = $(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`); const $widget = $(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`);
return {reset_button, $widget}; return {$reset_button, $widget};
}; };
run_test("basic_functions", () => { run_test("basic_functions", () => {
@@ -46,31 +46,31 @@ run_test("basic_functions", () => {
render_text: (text) => `rendered: ${text}`, render_text: (text) => `rendered: ${text}`,
}; };
const {reset_button, $widget} = setup_dropdown_zjquery_data(opts.widget_name); const {$reset_button, $widget} = setup_dropdown_zjquery_data(opts.widget_name);
const widget = new DropdownListWidget(opts); const widget = new DropdownListWidget(opts);
assert.equal(widget.value(), "one"); assert.equal(widget.value(), "one");
assert.equal(updated_value, undefined); // We haven't 'updated' the widget yet. assert.equal(updated_value, undefined); // We haven't 'updated' the widget yet.
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
widget.update("two"); widget.update("two");
assert.equal($widget.text(), "rendered: two"); assert.equal($widget.text(), "rendered: two");
assert.equal(widget.value(), "two"); assert.equal(widget.value(), "two");
assert.equal(updated_value, "two"); assert.equal(updated_value, "two");
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
widget.update(null); widget.update(null);
assert.equal($widget.text(), "translated: not set"); assert.equal($widget.text(), "translated: not set");
assert.equal(widget.value(), ""); assert.equal(widget.value(), "");
assert.equal(updated_value, null); assert.equal(updated_value, null);
assert.ok(!reset_button.visible()); assert.ok(!$reset_button.visible());
widget.update("four"); widget.update("four");
assert.equal($widget.text(), "translated: not set"); assert.equal($widget.text(), "translated: not set");
assert.equal(widget.value(), "four"); assert.equal(widget.value(), "four");
assert.equal(updated_value, "four"); assert.equal(updated_value, "four");
assert.ok(!reset_button.visible()); assert.ok(!$reset_button.visible());
}); });
run_test("no_default_value", () => { run_test("no_default_value", () => {
@@ -110,7 +110,7 @@ run_test("basic MDLW functions", () => {
default_text: $t({defaultMessage: "not set"}), default_text: $t({defaultMessage: "not set"}),
}; };
const {reset_button, $widget} = setup_multiselect_dropdown_zjquery_data(opts.widget_name); const {$reset_button, $widget} = setup_multiselect_dropdown_zjquery_data(opts.widget_name);
const widget = new MultiSelectDropdownListWidget(opts); const widget = new MultiSelectDropdownListWidget(opts);
function set_dropdown_variables(widget, value) { function set_dropdown_variables(widget, value) {
@@ -121,7 +121,7 @@ run_test("basic MDLW functions", () => {
assert.deepEqual(widget.value(), ["one"]); assert.deepEqual(widget.value(), ["one"]);
assert.equal(updated_value, undefined); assert.equal(updated_value, undefined);
assert.equal($widget.text(), "one"); assert.equal($widget.text(), "one");
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
set_dropdown_variables(widget, ["one", "two"]); set_dropdown_variables(widget, ["one", "two"]);
widget.update(widget.data_selected); widget.update(widget.data_selected);
@@ -129,7 +129,7 @@ run_test("basic MDLW functions", () => {
assert.equal($widget.text(), "one,two"); assert.equal($widget.text(), "one,two");
assert.deepEqual(widget.value(), ["one", "two"]); assert.deepEqual(widget.value(), ["one", "two"]);
assert.deepEqual(updated_value, ["one", "two"]); assert.deepEqual(updated_value, ["one", "two"]);
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
set_dropdown_variables(widget, ["one", "two", "three"]); set_dropdown_variables(widget, ["one", "two", "three"]);
widget.update(widget.data_selected); widget.update(widget.data_selected);
@@ -137,7 +137,7 @@ run_test("basic MDLW functions", () => {
assert.equal($widget.text(), "translated: 3 selected"); assert.equal($widget.text(), "translated: 3 selected");
assert.deepEqual(widget.value(), ["one", "two", "three"]); assert.deepEqual(widget.value(), ["one", "two", "three"]);
assert.deepEqual(updated_value, ["one", "two", "three"]); assert.deepEqual(updated_value, ["one", "two", "three"]);
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
set_dropdown_variables(widget, null); set_dropdown_variables(widget, null);
widget.update(widget.data_selected); widget.update(widget.data_selected);
@@ -145,7 +145,7 @@ run_test("basic MDLW functions", () => {
assert.equal($widget.text(), "translated: not set"); assert.equal($widget.text(), "translated: not set");
assert.equal(widget.value(), null); assert.equal(widget.value(), null);
assert.equal(updated_value, null); assert.equal(updated_value, null);
assert.ok(!reset_button.visible()); assert.ok(!$reset_button.visible());
set_dropdown_variables(widget, ["one"]); set_dropdown_variables(widget, ["one"]);
widget.update(widget.data_selected); widget.update(widget.data_selected);
@@ -153,7 +153,7 @@ run_test("basic MDLW functions", () => {
assert.equal($widget.text(), "one"); assert.equal($widget.text(), "one");
assert.deepEqual(widget.value(), ["one"]); assert.deepEqual(widget.value(), ["one"]);
assert.deepEqual(updated_value, ["one"]); assert.deepEqual(updated_value, ["one"]);
assert.ok(reset_button.visible()); assert.ok($reset_button.visible());
}); });
run_test("MDLW no_default_value", () => { run_test("MDLW no_default_value", () => {

View File

@@ -67,7 +67,7 @@ people.add_active_user(kitty);
*/ */
run_test("typing_events.render_notifications_for_narrow", ({override_rewire, mock_template}) => { run_test("typing_events.render_notifications_for_narrow", ({override_rewire, mock_template}) => {
// All typists are rendered in `#typing_notifications`. // All typists are rendered in `#typing_notifications`.
const typing_notifications = $("#typing_notifications"); const $typing_notifications = $("#typing_notifications");
const two_typing_users_ids = [anna.user_id, vronsky.user_id]; const two_typing_users_ids = [anna.user_id, vronsky.user_id];
const two_typing_users = [anna, vronsky]; const two_typing_users = [anna, vronsky];
@@ -107,7 +107,7 @@ run_test("typing_events.render_notifications_for_narrow", ({override_rewire, moc
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
// Make sure #typing_notifications's html content is set to the rendered template // Make sure #typing_notifications's html content is set to the rendered template
// which we mocked and gave a custom return value. // which we mocked and gave a custom return value.
assert.equal(typing_notifications.html(), two_typing_users_rendered_html); assert.equal($typing_notifications.html(), two_typing_users_rendered_html);
// Now we'll see how setting the second argument to `true` // Now we'll see how setting the second argument to `true`
// can be helpful in testing conditionals inside the template. // can be helpful in testing conditionals inside the template.
@@ -118,9 +118,9 @@ run_test("typing_events.render_notifications_for_narrow", ({override_rewire, moc
// Since we only have two(<MAX_USERS_TO_DISPLAY_NAME) typists, both of them // Since we only have two(<MAX_USERS_TO_DISPLAY_NAME) typists, both of them
// should be rendered but not 'Several people are typing…' // should be rendered but not 'Several people are typing…'
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(typing_notifications.html().includes(`${anna.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${anna.full_name} is typing…`));
assert.ok(typing_notifications.html().includes(`${vronsky.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${vronsky.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes("Several people are typing…")); assert.ok(!$typing_notifications.html().includes("Several people are typing…"));
// Change to having four typists and verify the rendered html has // Change to having four typists and verify the rendered html has
// 'Several people are typing…' but not the list of users. // 'Several people are typing…' but not the list of users.
@@ -128,9 +128,9 @@ run_test("typing_events.render_notifications_for_narrow", ({override_rewire, moc
override_rewire(typing_events, "get_users_typing_for_narrow", () => four_typing_users_ids); override_rewire(typing_events, "get_users_typing_for_narrow", () => four_typing_users_ids);
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(typing_notifications.html().includes("Several people are typing…")); assert.ok($typing_notifications.html().includes("Several people are typing…"));
assert.ok(!typing_notifications.html().includes(`${anna.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${anna.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${vronsky.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${vronsky.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${levin.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${levin.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${kitty.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${kitty.full_name} is typing…`));
}); });

View File

@@ -8,8 +8,8 @@ const blueslip = require("../zjsunit/zblueslip");
const $ = require("../zjsunit/zjquery"); const $ = require("../zjsunit/zjquery");
const {user_settings} = require("../zjsunit/zpage_params"); const {user_settings} = require("../zjsunit/zpage_params");
let window_stub; let $window_stub;
set_global("to_$", () => window_stub); set_global("to_$", () => $window_stub);
mock_esm("../../static/js/search", { mock_esm("../../static/js/search", {
update_button_visibility: () => {}, update_button_visibility: () => {},
@@ -165,7 +165,7 @@ function test_helper({override, override_rewire, change_tab}) {
} }
run_test("hash_interactions", ({override, override_rewire}) => { run_test("hash_interactions", ({override, override_rewire}) => {
window_stub = $.create("window-stub"); $window_stub = $.create("window-stub");
user_settings.default_view = "recent_topics"; user_settings.default_view = "recent_topics";
override_rewire(recent_topics_util, "is_visible", () => false); override_rewire(recent_topics_util, "is_visible", () => false);
@@ -189,7 +189,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#all_messages"; window.location.hash = "#all_messages";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[message_viewport, "stop_auto_scrolling"], [message_viewport, "stop_auto_scrolling"],
@@ -199,7 +199,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
]); ]);
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[message_viewport, "stop_auto_scrolling"], [message_viewport, "stop_auto_scrolling"],
@@ -211,7 +211,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#narrow/stream/Denmark"; window.location.hash = "#narrow/stream/Denmark";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[message_viewport, "stop_auto_scrolling"], [message_viewport, "stop_auto_scrolling"],
@@ -225,7 +225,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#narrow"; window.location.hash = "#narrow";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[message_viewport, "stop_auto_scrolling"], [message_viewport, "stop_auto_scrolling"],
@@ -240,7 +240,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#narrow/foo.foo"; window.location.hash = "#narrow/foo.foo";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[message_viewport, "stop_auto_scrolling"], [message_viewport, "stop_auto_scrolling"],
@@ -251,7 +251,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#streams/whatever"; window.location.hash = "#streams/whatever";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[stream_settings_ui, "launch"], [stream_settings_ui, "launch"],
@@ -261,7 +261,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#reload:send_after_reload=0..."; window.location.hash = "#reload:send_after_reload=0...";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([]); helper.assert_events([]);
// If it's reload hash it shouldn't show the default view. // If it's reload hash it shouldn't show the default view.
assert.equal(recent_topics_ui_shown, false); assert.equal(recent_topics_ui_shown, false);
@@ -269,25 +269,25 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#keyboard-shortcuts/whatever"; window.location.hash = "#keyboard-shortcuts/whatever";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([[overlays, "close_for_hash_change"], "info: keyboard-shortcuts"]); helper.assert_events([[overlays, "close_for_hash_change"], "info: keyboard-shortcuts"]);
window.location.hash = "#message-formatting/whatever"; window.location.hash = "#message-formatting/whatever";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([[overlays, "close_for_hash_change"], "info: message-formatting"]); helper.assert_events([[overlays, "close_for_hash_change"], "info: message-formatting"]);
window.location.hash = "#search-operators/whatever"; window.location.hash = "#search-operators/whatever";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([[overlays, "close_for_hash_change"], "info: search-operators"]); helper.assert_events([[overlays, "close_for_hash_change"], "info: search-operators"]);
window.location.hash = "#drafts"; window.location.hash = "#drafts";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[drafts, "launch"], [drafts, "launch"],
@@ -296,7 +296,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#settings/alert-words"; window.location.hash = "#settings/alert-words";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[settings, "launch"], [settings, "launch"],
@@ -305,7 +305,7 @@ run_test("hash_interactions", ({override, override_rewire}) => {
window.location.hash = "#organization/user-list-admin"; window.location.hash = "#organization/user-list-admin";
helper.clear_events(); helper.clear_events();
window_stub.trigger("hashchange"); $window_stub.trigger("hashchange");
helper.assert_events([ helper.assert_events([
[overlays, "close_for_hash_change"], [overlays, "close_for_hash_change"],
[admin, "launch"], [admin, "launch"],

View File

@@ -69,12 +69,12 @@ run_test("basics", ({override_rewire, mock_template}) => {
blueslip.expect("error", "Pill needs container."); blueslip.expect("error", "Pill needs container.");
input_pill.create(config); input_pill.create(config);
const pill_input = $.create("pill_input"); const $pill_input = $.create("pill_input");
const container = $.create("container"); const $container = $.create("container");
container.set_find_results(".input", pill_input); $container.set_find_results(".input", $pill_input);
blueslip.expect("error", "Pill needs create_item_from_text"); blueslip.expect("error", "Pill needs create_item_from_text");
config.container = container; config.$container = $container;
input_pill.create(config); input_pill.create(config);
blueslip.expect("error", "Pill needs get_text_from_item"); blueslip.expect("error", "Pill needs get_text_from_item");
@@ -101,9 +101,9 @@ run_test("basics", ({override_rewire, mock_template}) => {
let inserted_before; let inserted_before;
const expected_html = pill_html("JavaScript", "some_id1", example_img_link, status_emoji_info); const expected_html = pill_html("JavaScript", "some_id1", example_img_link, status_emoji_info);
pill_input.before = (elem) => { $pill_input.before = ($elem) => {
inserted_before = true; inserted_before = true;
assert.equal(elem.html(), expected_html); assert.equal($elem.html(), expected_html);
}; };
widget.appendValidatedData(item); widget.appendValidatedData(item);
@@ -134,27 +134,27 @@ function set_up() {
}, },
}; };
const pill_input = $.create("pill_input"); const $pill_input = $.create("pill_input");
pill_input[0] = {}; $pill_input[0] = {};
pill_input.before = () => {}; $pill_input.before = () => {};
const create_item_from_text = (text) => items[text]; const create_item_from_text = (text) => items[text];
const container = $.create("container"); const $container = $.create("container");
container.set_find_results(".input", pill_input); $container.set_find_results(".input", $pill_input);
const config = { const config = {
container, $container,
create_item_from_text, create_item_from_text,
get_text_from_item: (item) => item.display_value, get_text_from_item: (item) => item.display_value,
}; };
return { return {
config, config,
pill_input, $pill_input,
items, items,
container, $container,
}; };
} }
@@ -167,16 +167,16 @@ run_test("copy from pill", ({override_rewire, mock_template}) => {
override_random_id({override_rewire}); override_random_id({override_rewire});
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
widget.appendValue("blue,red"); widget.appendValue("blue,red");
const copy_handler = container.get_on_handler("copy", ".pill"); const copy_handler = $container.get_on_handler("copy", ".pill");
let copied_text; let copied_text;
const pill_stub = { const $pill_stub = {
data: (field) => { data: (field) => {
assert.equal(field, "id"); assert.equal(field, "id");
return "some_id2"; return "some_id2";
@@ -195,7 +195,7 @@ run_test("copy from pill", ({override_rewire, mock_template}) => {
preventDefault: noop, preventDefault: noop,
}; };
container.set_find_results(":focus", pill_stub); $container.set_find_results(":focus", $pill_stub);
copy_handler(e); copy_handler(e);
@@ -210,12 +210,12 @@ run_test("paste to input", ({mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const container = info.container; const $container = info.$container;
const items = info.items; const items = info.items;
const widget = input_pill.create(config); const widget = input_pill.create(config);
const paste_handler = container.get_on_handler("paste", ".input"); const paste_handler = $container.get_on_handler("paste", ".input");
const paste_text = "blue,yellow"; const paste_text = "blue,yellow";
@@ -233,7 +233,7 @@ run_test("paste to input", ({mock_template}) => {
document.execCommand = (cmd, _, text) => { document.execCommand = (cmd, _, text) => {
assert.equal(cmd, "insertText"); assert.equal(cmd, "insertText");
container.find(".input").text(text); $container.find(".input").text(text);
}; };
paste_handler(e); paste_handler(e);
@@ -257,12 +257,12 @@ run_test("arrows on pills", ({mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
widget.appendValue("blue,red"); widget.appendValue("blue,red");
const key_handler = container.get_on_handler("keydown", ".pill"); const key_handler = $container.get_on_handler("keydown", ".pill");
function test_key(c) { function test_key(c) {
key_handler({ key_handler({
@@ -273,7 +273,7 @@ run_test("arrows on pills", ({mock_template}) => {
let prev_focused = false; let prev_focused = false;
let next_focused = false; let next_focused = false;
const pill_stub = { const $pill_stub = {
prev: () => ({ prev: () => ({
trigger: (type) => { trigger: (type) => {
if (type === "focus") { if (type === "focus") {
@@ -290,7 +290,7 @@ run_test("arrows on pills", ({mock_template}) => {
}), }),
}; };
container.set_find_results(".pill:focus", pill_stub); $container.set_find_results(".pill:focus", $pill_stub);
// We use the same stub to test both arrows, since we don't // We use the same stub to test both arrows, since we don't
// actually cause any real state changes here. We stub out // actually cause any real state changes here. We stub out
@@ -310,16 +310,16 @@ run_test("left arrow on input", ({mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
widget.appendValue("blue,red"); widget.appendValue("blue,red");
const key_handler = container.get_on_handler("keydown", ".input"); const key_handler = $container.get_on_handler("keydown", ".input");
let last_pill_focused = false; let last_pill_focused = false;
container.set_find_results(".pill", { $container.set_find_results(".pill", {
last: () => ({ last: () => ({
trigger: (type) => { trigger: (type) => {
if (type === "focus") { if (type === "focus") {
@@ -345,17 +345,17 @@ run_test("comma", ({mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const items = info.items; const items = info.items;
const pill_input = info.pill_input; const $pill_input = info.$pill_input;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
widget.appendValue("blue,red"); widget.appendValue("blue,red");
assert.deepEqual(widget.items(), [items.blue, items.red]); assert.deepEqual(widget.items(), [items.blue, items.red]);
const key_handler = container.get_on_handler("keydown", ".input"); const key_handler = $container.get_on_handler("keydown", ".input");
pill_input.text(" yel"); $pill_input.text(" yel");
key_handler({ key_handler({
key: ",", key: ",",
@@ -364,7 +364,7 @@ run_test("comma", ({mock_template}) => {
assert.deepEqual(widget.items(), [items.blue, items.red]); assert.deepEqual(widget.items(), [items.blue, items.red]);
pill_input.text(" yellow"); $pill_input.text(" yellow");
key_handler({ key_handler({
key: ",", key: ",",
@@ -383,14 +383,14 @@ run_test("Enter key with text", ({mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const items = info.items; const items = info.items;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
widget.appendValue("blue,red"); widget.appendValue("blue,red");
assert.deepEqual(widget.items(), [items.blue, items.red]); assert.deepEqual(widget.items(), [items.blue, items.red]);
const key_handler = container.get_on_handler("keydown", ".input"); const key_handler = $container.get_on_handler("keydown", ".input");
key_handler({ key_handler({
key: "Enter", key: "Enter",
@@ -415,13 +415,13 @@ run_test("insert_remove", ({override_rewire, mock_template}) => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const pill_input = info.pill_input; const $pill_input = info.$pill_input;
const items = info.items; const items = info.items;
const container = info.container; const $container = info.$container;
const inserted_html = []; const inserted_html = [];
pill_input.before = (elem) => { $pill_input.before = ($elem) => {
inserted_html.push(elem.html()); inserted_html.push($elem.html());
}; };
const widget = input_pill.create(config); const widget = input_pill.create(config);
@@ -450,11 +450,11 @@ run_test("insert_remove", ({override_rewire, mock_template}) => {
assert.deepEqual(widget.items(), [items.blue, items.red, items.yellow]); assert.deepEqual(widget.items(), [items.blue, items.red, items.yellow]);
assert.equal(pill_input.text(), "chartreuse, mauve"); assert.equal($pill_input.text(), "chartreuse, mauve");
assert.equal(widget.is_pending(), true); assert.equal(widget.is_pending(), true);
widget.clear_text(); widget.clear_text();
assert.equal(pill_input.text(), ""); assert.equal($pill_input.text(), "");
assert.equal(widget.is_pending(), false); assert.equal(widget.is_pending(), false);
let color_removed; let color_removed;
@@ -469,7 +469,7 @@ run_test("insert_remove", ({override_rewire, mock_template}) => {
pill.$element.remove = set_colored_removed_func(pill.item.display_value); pill.$element.remove = set_colored_removed_func(pill.item.display_value);
} }
let key_handler = container.get_on_handler("keydown", ".input"); let key_handler = $container.get_on_handler("keydown", ".input");
key_handler({ key_handler({
key: "Backspace", key: "Backspace",
@@ -486,7 +486,7 @@ run_test("insert_remove", ({override_rewire, mock_template}) => {
let next_pill_focused = false; let next_pill_focused = false;
const next_pill_stub = { const $next_pill_stub = {
trigger: (type) => { trigger: (type) => {
if (type === "focus") { if (type === "focus") {
next_pill_focused = true; next_pill_focused = true;
@@ -494,17 +494,17 @@ run_test("insert_remove", ({override_rewire, mock_template}) => {
}, },
}; };
const focus_pill_stub = { const $focus_pill_stub = {
next: () => next_pill_stub, next: () => $next_pill_stub,
data: (field) => { data: (field) => {
assert.equal(field, "id"); assert.equal(field, "id");
return "some_id1"; return "some_id1";
}, },
}; };
container.set_find_results(".pill:focus", focus_pill_stub); $container.set_find_results(".pill:focus", $focus_pill_stub);
key_handler = container.get_on_handler("keydown", ".pill"); key_handler = $container.get_on_handler("keydown", ".pill");
key_handler({ key_handler({
key: "Backspace", key: "Backspace",
preventDefault: noop, preventDefault: noop,
@@ -526,7 +526,7 @@ run_test("exit button on pill", ({override_rewire, mock_template}) => {
const config = info.config; const config = info.config;
const items = info.items; const items = info.items;
const container = info.container; const $container = info.$container;
const widget = input_pill.create(config); const widget = input_pill.create(config);
@@ -539,7 +539,7 @@ run_test("exit button on pill", ({override_rewire, mock_template}) => {
let next_pill_focused = false; let next_pill_focused = false;
const next_pill_stub = { const $next_pill_stub = {
trigger: (type) => { trigger: (type) => {
if (type === "focus") { if (type === "focus") {
next_pill_focused = true; next_pill_focused = true;
@@ -547,8 +547,8 @@ run_test("exit button on pill", ({override_rewire, mock_template}) => {
}, },
}; };
const curr_pill_stub = { const $curr_pill_stub = {
next: () => next_pill_stub, next: () => $next_pill_stub,
data: (field) => { data: (field) => {
assert.equal(field, "id"); assert.equal(field, "id");
return "some_id1"; return "some_id1";
@@ -559,7 +559,7 @@ run_test("exit button on pill", ({override_rewire, mock_template}) => {
to_$: () => ({ to_$: () => ({
closest: (sel) => { closest: (sel) => {
assert.equal(sel, ".pill"); assert.equal(sel, ".pill");
return curr_pill_stub; return $curr_pill_stub;
}, },
}), }),
}; };
@@ -567,7 +567,7 @@ run_test("exit button on pill", ({override_rewire, mock_template}) => {
const e = { const e = {
stopPropagation: noop, stopPropagation: noop,
}; };
const exit_click_handler = container.get_on_handler("click", ".exit"); const exit_click_handler = $container.get_on_handler("click", ".exit");
exit_click_handler.call(exit_button_stub, e); exit_click_handler.call(exit_button_stub, e);
@@ -580,13 +580,13 @@ run_test("misc things", () => {
const info = set_up(); const info = set_up();
const config = info.config; const config = info.config;
const container = info.container; const $container = info.$container;
const pill_input = info.pill_input; const $pill_input = info.$pill_input;
const widget = input_pill.create(config); const widget = input_pill.create(config);
// animation // animation
const animation_end_handler = container.get_on_handler("animationend", ".input"); const animation_end_handler = $container.get_on_handler("animationend", ".input");
let shake_class_removed = false; let shake_class_removed = false;
@@ -614,17 +614,17 @@ run_test("misc things", () => {
}); });
// click on container // click on container
const container_click_handler = container.get_on_handler("click"); const container_click_handler = $container.get_on_handler("click");
const stub = $.create("the-pill-container"); const $stub = $.create("the-pill-container");
stub.set_find_results(".input", pill_input); $stub.set_find_results(".input", $pill_input);
stub.is = (sel) => { $stub.is = (sel) => {
assert.equal(sel, ".pill-container"); assert.equal(sel, ".pill-container");
return true; return true;
}; };
const this_ = { const this_ = {
to_$: () => stub, to_$: () => $stub,
}; };
container_click_handler.call(this_, {target: this_}); container_click_handler.call(this_, {target: this_});
@@ -637,18 +637,18 @@ run_test("appendValue/clear", ({mock_template}) => {
return html; return html;
}); });
const pill_input = $.create("pill_input"); const $pill_input = $.create("pill_input");
const container = $.create("container"); const $container = $.create("container");
container.set_find_results(".input", pill_input); $container.set_find_results(".input", $pill_input);
const config = { const config = {
container, $container,
create_item_from_text: (s) => ({type: "color", display_value: s}), create_item_from_text: (s) => ({type: "color", display_value: s}),
get_text_from_item: (s) => s.display_value, get_text_from_item: (s) => s.display_value,
}; };
pill_input.before = () => {}; $pill_input.before = () => {};
pill_input[0] = {}; $pill_input[0] = {};
const widget = input_pill.create(config); const widget = input_pill.create(config);
@@ -672,5 +672,5 @@ run_test("appendValue/clear", ({mock_template}) => {
// Note that we remove colors in the reverse order that we inserted. // Note that we remove colors in the reverse order that we inserted.
assert.deepEqual(removed_colors, ["blue", "yellow", "red"]); assert.deepEqual(removed_colors, ["blue", "yellow", "red"]);
assert.equal(pill_input[0].textContent, ""); assert.equal($pill_input[0].textContent, "");
}); });

View File

@@ -7,9 +7,9 @@ const $ = require("../zjsunit/zjquery");
const keydown_util = zrequire("keydown_util"); const keydown_util = zrequire("keydown_util");
run_test("test_early_returns", () => { run_test("test_early_returns", () => {
const stub = $.create("stub"); const $stub = $.create("stub");
const opts = { const opts = {
elem: stub, $elem: $stub,
handlers: { handlers: {
ArrowLeft: () => { ArrowLeft: () => {
throw new Error("do not dispatch this with alt key"); throw new Error("do not dispatch this with alt key");
@@ -24,14 +24,14 @@ run_test("test_early_returns", () => {
key: "a", // not in keys key: "a", // not in keys
}; };
stub.trigger(e1); $stub.trigger(e1);
const e2 = { const e2 = {
type: "keydown", type: "keydown",
key: "Enter", // no handler key: "Enter", // no handler
}; };
stub.trigger(e2); $stub.trigger(e2);
const e3 = { const e3 = {
type: "keydown", type: "keydown",
@@ -39,5 +39,5 @@ run_test("test_early_returns", () => {
altKey: true, // let browser handle altKey: true, // let browser handle
}; };
stub.trigger(e3); $stub.trigger(e3);
}); });

View File

@@ -30,21 +30,21 @@ function test(label, f) {
} }
test("pan_and_zoom", ({override_rewire}) => { test("pan_and_zoom", ({override_rewire}) => {
const img = $.create("img-stub"); const $img = $.create("img-stub");
const link = $.create("link-stub"); const $link = $.create("link-stub");
const msg = $.create("msg-stub"); const $msg = $.create("msg-stub");
$(img).closest = () => []; $($img).closest = () => [];
img.set_parent(link); $img.set_parent($link);
link.closest = () => msg; $link.closest = () => $msg;
override_rewire(rows, "id", (row) => { override_rewire(rows, "id", ($row) => {
assert.equal(row, msg); assert.equal($row, $msg);
return 1234; return 1234;
}); });
img.attr("src", "example"); $img.attr("src", "example");
let fetched_zid; let fetched_zid;
@@ -55,25 +55,25 @@ test("pan_and_zoom", ({override_rewire}) => {
override_rewire(lightbox, "render_lightbox_list_images", () => {}); override_rewire(lightbox, "render_lightbox_list_images", () => {});
const open_image = lightbox.build_open_image_function(); const open_image = lightbox.build_open_image_function();
open_image(img); open_image($img);
assert.equal(fetched_zid, 1234); assert.equal(fetched_zid, 1234);
}); });
test("youtube", ({override_rewire}) => { test("youtube", ({override_rewire}) => {
const href = "https://youtube.com/some-random-clip"; const href = "https://youtube.com/some-random-clip";
const img = $.create("img-stub"); const $img = $.create("img-stub");
const link = $.create("link-stub"); const $link = $.create("link-stub");
const msg = $.create("msg-stub"); const $msg = $.create("msg-stub");
override_rewire(rows, "id", (row) => { override_rewire(rows, "id", ($row) => {
assert.equal(row, msg); assert.equal($row, $msg);
return 4321; return 4321;
}); });
$(img).attr("src", href); $($img).attr("src", href);
$(img).closest = (sel) => { $($img).closest = (sel) => {
if (sel === ".youtube-video") { if (sel === ".youtube-video") {
// We just need a nonempty array to // We just need a nonempty array to
// set is_youtube_video to true. // set is_youtube_video to true.
@@ -82,13 +82,13 @@ test("youtube", ({override_rewire}) => {
return []; return [];
}; };
img.set_parent(link); $img.set_parent($link);
link.closest = () => msg; $link.closest = () => $msg;
link.attr("href", href); $link.attr("href", href);
override_rewire(lightbox, "render_lightbox_list_images", () => {}); override_rewire(lightbox, "render_lightbox_list_images", () => {});
const open_image = lightbox.build_open_image_function(); const open_image = lightbox.build_open_image_function();
open_image(img); open_image($img);
assert.equal($(".image-actions .open").attr("href"), href); assert.equal($(".image-actions .open").attr("href"), href);
}); });

View File

@@ -70,12 +70,12 @@ run_test("single item list", ({override}) => {
}); });
const cursor = new ListCursor(conf); const cursor = new ListCursor(conf);
const li_stub = { const $li_stub = {
length: 1, length: 1,
addClass: () => {}, addClass: () => {},
}; };
override(conf.list, "find_li", () => li_stub); override(conf.list, "find_li", () => $li_stub);
override(cursor, "adjust_scroll", () => {}); override(cursor, "adjust_scroll", () => {});
cursor.go_to(valid_key); cursor.go_to(valid_key);

View File

@@ -41,81 +41,81 @@ const ListWidget = zrequire("list_widget");
// in the real code. // in the real code.
function make_container() { function make_container() {
const container = {}; const $container = {};
container.length = () => 1; $container.length = () => 1;
container.is = () => false; $container.is = () => false;
container.css = (prop) => { $container.css = (prop) => {
assert.equal(prop, "max-height"); assert.equal(prop, "max-height");
return "none"; return "none";
}; };
// Make our append function just set a field we can // Make our append function just set a field we can
// check in our tests. // check in our tests.
container.append = (data) => { $container.append = ($data) => {
container.appended_data = data; $container.$appended_data = $data;
}; };
return container; return $container;
} }
function make_scroll_container() { function make_scroll_container() {
const scroll_container = {}; const $scroll_container = {};
scroll_container.cleared = false; $scroll_container.cleared = false;
// Capture the scroll callback so we can call it in // Capture the scroll callback so we can call it in
// our tests. // our tests.
scroll_container.on = (ev, f) => { $scroll_container.on = (ev, f) => {
assert.equal(ev, "scroll.list_widget_container"); assert.equal(ev, "scroll.list_widget_container");
scroll_container.call_scroll = () => { $scroll_container.call_scroll = () => {
f.call(scroll_container); f.call($scroll_container);
}; };
}; };
scroll_container.off = (ev) => { $scroll_container.off = (ev) => {
assert.equal(ev, "scroll.list_widget_container"); assert.equal(ev, "scroll.list_widget_container");
scroll_container.cleared = true; $scroll_container.cleared = true;
}; };
return scroll_container; return $scroll_container;
} }
function make_sort_container() { function make_sort_container() {
const sort_container = {}; const $sort_container = {};
sort_container.cleared = false; $sort_container.cleared = false;
sort_container.on = (ev, sel, f) => { $sort_container.on = (ev, sel, f) => {
assert.equal(ev, "click.list_widget_sort"); assert.equal(ev, "click.list_widget_sort");
assert.equal(sel, "[data-sort]"); assert.equal(sel, "[data-sort]");
sort_container.f = f; $sort_container.f = f;
}; };
sort_container.off = (ev) => { $sort_container.off = (ev) => {
assert.equal(ev, "click.list_widget_sort"); assert.equal(ev, "click.list_widget_sort");
sort_container.cleared = true; $sort_container.cleared = true;
}; };
return sort_container; return $sort_container;
} }
function make_filter_element() { function make_filter_element() {
const element = {}; const $element = {};
element.cleared = false; $element.cleared = false;
element.on = (ev, f) => { $element.on = (ev, f) => {
assert.equal(ev, "input.list_widget_filter"); assert.equal(ev, "input.list_widget_filter");
element.f = f; $element.f = f;
}; };
element.off = (ev) => { $element.off = (ev) => {
assert.equal(ev, "input.list_widget_filter"); assert.equal(ev, "input.list_widget_filter");
element.cleared = true; $element.cleared = true;
}; };
return element; return $element;
} }
function make_search_input() { function make_search_input() {
@@ -143,15 +143,15 @@ function div(item) {
} }
run_test("scrolling", () => { run_test("scrolling", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const items = []; const items = [];
let get_scroll_element_called = false; let get_scroll_element_called = false;
ui.get_scroll_element = (element) => { ui.get_scroll_element = ($element) => {
get_scroll_element_called = true; get_scroll_element_called = true;
return element; return $element;
}; };
for (let i = 0; i < 200; i += 1) { for (let i = 0; i < 200; i += 1) {
@@ -160,38 +160,38 @@ run_test("scrolling", () => {
const opts = { const opts = {
modifier: (item) => item, modifier: (item) => item,
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}; };
container.html = (html) => { $container.html = (html) => {
assert.equal(html, ""); assert.equal(html, "");
}; };
ListWidget.create(container, items, opts); ListWidget.create($container, items, opts);
assert.deepEqual(container.appended_data.html(), items.slice(0, 80).join("")); assert.deepEqual($container.$appended_data.html(), items.slice(0, 80).join(""));
assert.equal(get_scroll_element_called, true); assert.equal(get_scroll_element_called, true);
// Set up our fake geometry so it forces a scroll action. // Set up our fake geometry so it forces a scroll action.
scroll_container.scrollTop = 180; $scroll_container.scrollTop = 180;
scroll_container.clientHeight = 100; $scroll_container.clientHeight = 100;
scroll_container.scrollHeight = 260; $scroll_container.scrollHeight = 260;
// Scrolling gets the next two elements from the list into // Scrolling gets the next two elements from the list into
// our widget. // our widget.
scroll_container.call_scroll(); $scroll_container.call_scroll();
assert.deepEqual(container.appended_data.html(), items.slice(80, 100).join("")); assert.deepEqual($container.$appended_data.html(), items.slice(80, 100).join(""));
}); });
run_test("not_scrolling", () => { run_test("not_scrolling", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const items = []; const items = [];
let get_scroll_element_called = false; let get_scroll_element_called = false;
ui.get_scroll_element = (element) => { ui.get_scroll_element = ($element) => {
get_scroll_element_called = true; get_scroll_element_called = true;
return element; return $element;
}; };
let post_scroll__pre_render_callback_called = false; let post_scroll__pre_render_callback_called = false;
@@ -211,54 +211,54 @@ run_test("not_scrolling", () => {
const opts = { const opts = {
modifier: (item) => item, modifier: (item) => item,
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
is_scroll_position_for_render: () => false, is_scroll_position_for_render: () => false,
post_scroll__pre_render_callback, post_scroll__pre_render_callback,
get_min_load_count, get_min_load_count,
}; };
container.html = (html) => { $container.html = (html) => {
assert.equal(html, ""); assert.equal(html, "");
}; };
ListWidget.create(container, items, opts); ListWidget.create($container, items, opts);
assert.deepEqual(container.appended_data.html(), items.slice(0, 80).join("")); assert.deepEqual($container.$appended_data.html(), items.slice(0, 80).join(""));
assert.equal(get_scroll_element_called, true); assert.equal(get_scroll_element_called, true);
// Set up our fake geometry. // Set up our fake geometry.
scroll_container.scrollTop = 180; $scroll_container.scrollTop = 180;
scroll_container.clientHeight = 100; $scroll_container.clientHeight = 100;
scroll_container.scrollHeight = 260; $scroll_container.scrollHeight = 260;
// Since `should_render` is always false, no elements will be // Since `should_render` is always false, no elements will be
// added regardless of scrolling. // added regardless of scrolling.
scroll_container.call_scroll(); $scroll_container.call_scroll();
// appended_data remains the same. // $appended_data remains the same.
assert.deepEqual(container.appended_data.html(), items.slice(0, 80).join("")); assert.deepEqual($container.$appended_data.html(), items.slice(0, 80).join(""));
assert.equal(post_scroll__pre_render_callback_called, true); assert.equal(post_scroll__pre_render_callback_called, true);
assert.equal(get_min_load_count_called, true); assert.equal(get_min_load_count_called, true);
}); });
run_test("filtering", () => { run_test("filtering", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const search_input = make_search_input(); const $search_input = make_search_input();
const list = ["apple", "banana", "carrot", "dog", "egg", "fence", "grape"]; const list = ["apple", "banana", "carrot", "dog", "egg", "fence", "grape"];
const opts = { const opts = {
filter: { filter: {
element: search_input, $element: $search_input,
predicate: (item, value) => item.includes(value), predicate: (item, value) => item.includes(value),
}, },
modifier: (item) => div(item), modifier: (item) => div(item),
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}; };
container.html = (html) => { $container.html = (html) => {
assert.equal(html, ""); assert.equal(html, "");
}; };
const widget = ListWidget.create(container, list, opts); const widget = ListWidget.create($container, list, opts);
let expected_html = let expected_html =
"<div>apple</div>" + "<div>apple</div>" +
@@ -269,45 +269,45 @@ run_test("filtering", () => {
"<div>fence</div>" + "<div>fence</div>" +
"<div>grape</div>"; "<div>grape</div>";
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
// Filtering will pick out dog/egg/grape when we put "g" // Filtering will pick out dog/egg/grape when we put "g"
// into our search input. (This uses the default filter, which // into our search input. (This uses the default filter, which
// is a glorified indexOf call.) // is a glorified indexOf call.)
search_input.val = () => "g"; $search_input.val = () => "g";
search_input.simulate_input_event(); $search_input.simulate_input_event();
assert.deepEqual(widget.get_current_list(), ["dog", "egg", "grape"]); assert.deepEqual(widget.get_current_list(), ["dog", "egg", "grape"]);
expected_html = "<div>dog</div><div>egg</div><div>grape</div>"; expected_html = "<div>dog</div><div>egg</div><div>grape</div>";
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
// We can insert new data into the widget. // We can insert new data into the widget.
const new_data = ["greta", "faye", "gary", "frank", "giraffe", "fox"]; const new_data = ["greta", "faye", "gary", "frank", "giraffe", "fox"];
widget.replace_list_data(new_data); widget.replace_list_data(new_data);
expected_html = "<div>greta</div><div>gary</div><div>giraffe</div>"; expected_html = "<div>greta</div><div>gary</div><div>giraffe</div>";
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
}); });
run_test("no filtering", () => { run_test("no filtering", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
container.html = () => {}; $container.html = () => {};
let callback_called = false; let callback_called = false;
// Opts does not require a filter key. // Opts does not require a filter key.
const opts = { const opts = {
modifier: (item) => div(item), modifier: (item) => div(item),
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
callback_after_render: () => { callback_after_render: () => {
callback_called = true; callback_called = true;
}, },
}; };
const widget = ListWidget.create(container, ["apple", "banana"], opts); const widget = ListWidget.create($container, ["apple", "banana"], opts);
widget.render(); widget.render();
assert.deepEqual(callback_called, true); assert.deepEqual(callback_called, true);
const expected_html = "<div>apple</div><div>banana</div>"; const expected_html = "<div>apple</div><div>banana</div>";
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
}); });
function sort_button(opts) { function sort_button(opts) {
@@ -336,7 +336,7 @@ function sort_button(opts) {
const classList = new Set(); const classList = new Set();
const button = { const $button = {
data, data,
closest: lookup(".progressive-table-wrapper", { closest: lookup(".progressive-table-wrapper", {
data: lookup("list-widget", opts.list_name), data: lookup("list-widget", opts.list_name),
@@ -351,47 +351,47 @@ function sort_button(opts) {
siblings: lookup(".active", { siblings: lookup(".active", {
removeClass: (cls) => { removeClass: (cls) => {
assert.equal(cls, "active"); assert.equal(cls, "active");
button.siblings_deactivated = true; $button.siblings_deactivated = true;
}, },
}), }),
siblings_deactivated: false, siblings_deactivated: false,
to_jquery: () => button, to_jquery: () => $button,
}; };
return button; return $button;
} }
run_test("wire up filter element", () => { run_test("wire up filter element", () => {
const lst = ["alice", "JESSE", "moses", "scott", "Sean", "Xavier"]; const lst = ["alice", "JESSE", "moses", "scott", "Sean", "Xavier"];
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const filter_element = make_filter_element(); const $filter_element = make_filter_element();
// We don't care about what gets drawn initially. // We don't care about what gets drawn initially.
container.html = () => {}; $container.html = () => {};
const opts = { const opts = {
filter: { filter: {
filterer: (list, value) => list.filter((item) => item.toLowerCase().includes(value)), filterer: (list, value) => list.filter((item) => item.toLowerCase().includes(value)),
element: filter_element, $element: $filter_element,
}, },
modifier: (s) => "(" + s + ")", modifier: (s) => "(" + s + ")",
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}; };
ListWidget.create(container, lst, opts); ListWidget.create($container, lst, opts);
filter_element.f.apply({value: "se"}); $filter_element.f.apply({value: "se"});
assert.equal(container.appended_data.html(), "(JESSE)(moses)(Sean)"); assert.equal($container.$appended_data.html(), "(JESSE)(moses)(Sean)");
}); });
run_test("sorting", () => { run_test("sorting", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const sort_container = make_sort_container(); const $sort_container = make_sort_container();
let cleared; let cleared;
container.html = (html) => { $container.html = (html) => {
assert.equal(html, ""); assert.equal(html, "");
cleared = true; cleared = true;
}; };
@@ -406,22 +406,22 @@ run_test("sorting", () => {
const opts = { const opts = {
name: "sorting-list", name: "sorting-list",
parent_container: sort_container, $parent_container: $sort_container,
modifier: (item) => div(item.name) + div(item.salary), modifier: (item) => div(item.name) + div(item.salary),
filter: { filter: {
predicate: () => true, predicate: () => true,
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}; };
function html_for(people) { function html_for(people) {
return people.map((item) => opts.modifier(item)).join(""); return people.map((item) => opts.modifier(item)).join("");
} }
ListWidget.create(container, list, opts); ListWidget.create($container, list, opts);
let button_opts; let button_opts;
let button; let $button;
let expected_html; let expected_html;
button_opts = { button_opts = {
@@ -431,31 +431,31 @@ run_test("sorting", () => {
active: false, active: false,
}; };
button = sort_button(button_opts); $button = sort_button(button_opts);
sort_container.f.apply(button); $sort_container.f.apply($button);
assert.ok(cleared); assert.ok(cleared);
assert.ok(button.siblings_deactivated); assert.ok($button.siblings_deactivated);
expected_html = html_for([alice, bob, cal, dave, ellen]); expected_html = html_for([alice, bob, cal, dave, ellen]);
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
// Hit same button again to reverse the data. // Hit same button again to reverse the data.
cleared = false; cleared = false;
sort_container.f.apply(button); $sort_container.f.apply($button);
assert.ok(cleared); assert.ok(cleared);
expected_html = html_for([ellen, dave, cal, bob, alice]); expected_html = html_for([ellen, dave, cal, bob, alice]);
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
assert.ok(button.hasClass("descend")); assert.ok($button.hasClass("descend"));
// And then hit a third time to go back to the forward sort. // And then hit a third time to go back to the forward sort.
cleared = false; cleared = false;
sort_container.f.apply(button); $sort_container.f.apply($button);
assert.ok(cleared); assert.ok(cleared);
expected_html = html_for([alice, bob, cal, dave, ellen]); expected_html = html_for([alice, bob, cal, dave, ellen]);
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
assert.ok(!button.hasClass("descend")); assert.ok(!$button.hasClass("descend"));
// Now try a numeric sort. // Now try a numeric sort.
button_opts = { button_opts = {
@@ -465,32 +465,32 @@ run_test("sorting", () => {
active: false, active: false,
}; };
button = sort_button(button_opts); $button = sort_button(button_opts);
cleared = false; cleared = false;
button.siblings_deactivated = false; $button.siblings_deactivated = false;
sort_container.f.apply(button); $sort_container.f.apply($button);
assert.ok(cleared); assert.ok(cleared);
assert.ok(button.siblings_deactivated); assert.ok($button.siblings_deactivated);
expected_html = html_for([dave, cal, bob, alice, ellen]); expected_html = html_for([dave, cal, bob, alice, ellen]);
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
// Hit same button again to reverse the numeric sort. // Hit same button again to reverse the numeric sort.
cleared = false; cleared = false;
sort_container.f.apply(button); $sort_container.f.apply($button);
assert.ok(cleared); assert.ok(cleared);
expected_html = html_for([ellen, alice, bob, cal, dave]); expected_html = html_for([ellen, alice, bob, cal, dave]);
assert.deepEqual(container.appended_data.html(), expected_html); assert.deepEqual($container.$appended_data.html(), expected_html);
assert.ok(button.hasClass("descend")); assert.ok($button.hasClass("descend"));
}); });
run_test("custom sort", () => { run_test("custom sort", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
container.html = () => {}; $container.html = () => {};
const n42 = {x: 6, y: 7}; const n42 = {x: 6, y: 7};
const n43 = {x: 1, y: 43}; const n43 = {x: 1, y: 43};
@@ -506,7 +506,7 @@ run_test("custom sort", () => {
return a.x * a.y - b.x * b.y; return a.x * a.y - b.x * b.y;
} }
ListWidget.create(container, list, { ListWidget.create($container, list, {
name: "custom-sort-list", name: "custom-sort-list",
modifier: (n) => "(" + n.x + ", " + n.y + ")", modifier: (n) => "(" + n.x + ", " + n.y + ")",
sort_fields: { sort_fields: {
@@ -514,15 +514,15 @@ run_test("custom sort", () => {
x_value: sort_by_x, x_value: sort_by_x,
}, },
init_sort: [sort_by_product], init_sort: [sort_by_product],
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
assert.deepEqual(container.appended_data.html(), "(6, 7)(1, 43)(4, 11)"); assert.deepEqual($container.$appended_data.html(), "(6, 7)(1, 43)(4, 11)");
const widget = ListWidget.get("custom-sort-list"); const widget = ListWidget.get("custom-sort-list");
widget.sort("x_value"); widget.sort("x_value");
assert.deepEqual(container.appended_data.html(), "(1, 43)(4, 11)(6, 7)"); assert.deepEqual($container.$appended_data.html(), "(1, 43)(4, 11)(6, 7)");
// We can sort without registering the function, too. // We can sort without registering the function, too.
function sort_by_y(a, b) { function sort_by_y(a, b) {
@@ -530,97 +530,97 @@ run_test("custom sort", () => {
} }
widget.sort(sort_by_y); widget.sort(sort_by_y);
assert.deepEqual(container.appended_data.html(), "(6, 7)(4, 11)(1, 43)"); assert.deepEqual($container.$appended_data.html(), "(6, 7)(4, 11)(1, 43)");
}); });
run_test("clear_event_handlers", () => { run_test("clear_event_handlers", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const sort_container = make_sort_container(); const $sort_container = make_sort_container();
const filter_element = make_filter_element(); const $filter_element = make_filter_element();
// We don't care about actual data for this test. // We don't care about actual data for this test.
const list = []; const list = [];
container.html = () => {}; $container.html = () => {};
const opts = { const opts = {
name: "list-we-create-twice", name: "list-we-create-twice",
parent_container: sort_container, $parent_container: $sort_container,
modifier: () => {}, modifier: () => {},
filter: { filter: {
element: filter_element, $element: $filter_element,
predicate: () => true, predicate: () => true,
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}; };
// Create it the first time. // Create it the first time.
ListWidget.create(container, list, opts); ListWidget.create($container, list, opts);
assert.equal(sort_container.cleared, false); assert.equal($sort_container.cleared, false);
assert.equal(scroll_container.cleared, false); assert.equal($scroll_container.cleared, false);
assert.equal(filter_element.cleared, false); assert.equal($filter_element.cleared, false);
// The second time we'll clear the old events. // The second time we'll clear the old events.
ListWidget.create(container, list, opts); ListWidget.create($container, list, opts);
assert.equal(sort_container.cleared, true); assert.equal($sort_container.cleared, true);
assert.equal(scroll_container.cleared, true); assert.equal($scroll_container.cleared, true);
assert.equal(filter_element.cleared, true); assert.equal($filter_element.cleared, true);
}); });
run_test("errors", () => { run_test("errors", () => {
// We don't care about actual data for this test. // We don't care about actual data for this test.
const list = ["stub"]; const list = ["stub"];
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
blueslip.expect("error", "Need opts to create widget."); blueslip.expect("error", "Need opts to create widget.");
ListWidget.create(container, list); ListWidget.create($container, list);
blueslip.reset(); blueslip.reset();
blueslip.expect("error", "simplebar_container is missing."); blueslip.expect("error", "$simplebar_container is missing.");
ListWidget.create(container, list, { ListWidget.create($container, list, {
modifier: "hello world", modifier: "hello world",
}); });
blueslip.reset(); blueslip.reset();
blueslip.expect("error", "get_item should be a function"); blueslip.expect("error", "get_item should be a function");
ListWidget.create(container, list, { ListWidget.create($container, list, {
get_item: "not a function", get_item: "not a function",
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
blueslip.expect("error", "Filter predicate is not a function."); blueslip.expect("error", "Filter predicate is not a function.");
ListWidget.create(container, list, { ListWidget.create($container, list, {
filter: { filter: {
predicate: "wrong type", predicate: "wrong type",
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
blueslip.expect("error", "Filterer and predicate are mutually exclusive."); blueslip.expect("error", "Filterer and predicate are mutually exclusive.");
ListWidget.create(container, list, { ListWidget.create($container, list, {
filter: { filter: {
filterer: () => true, filterer: () => true,
predicate: () => true, predicate: () => true,
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
blueslip.expect("error", "Filter filterer is not a function (or missing)."); blueslip.expect("error", "Filter filterer is not a function (or missing).");
ListWidget.create(container, list, { ListWidget.create($container, list, {
filter: {}, filter: {},
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
container.html = () => {}; $container.html = () => {};
blueslip.expect("error", "List item is not a string: 999"); blueslip.expect("error", "List item is not a string: 999");
ListWidget.create(container, list, { ListWidget.create($container, list, {
modifier: () => 999, modifier: () => 999,
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
}); });
@@ -648,14 +648,14 @@ run_test("sort helpers", () => {
}); });
run_test("replace_list_data w/filter update", () => { run_test("replace_list_data w/filter update", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
container.html = () => {}; $container.html = () => {};
const list = [1, 2, 3, 4]; const list = [1, 2, 3, 4];
let num_updates = 0; let num_updates = 0;
ListWidget.create(container, list, { ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (n) => "(" + n.toString() + ")", modifier: (n) => "(" + n.toString() + ")",
filter: { filter: {
@@ -664,19 +664,19 @@ run_test("replace_list_data w/filter update", () => {
num_updates += 1; num_updates += 1;
}, },
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
assert.equal(num_updates, 0); assert.equal(num_updates, 0);
assert.deepEqual(container.appended_data.html(), "(2)(4)"); assert.deepEqual($container.$appended_data.html(), "(2)(4)");
const widget = ListWidget.get("replace-list"); const widget = ListWidget.get("replace-list");
widget.replace_list_data([5, 6, 7, 8]); widget.replace_list_data([5, 6, 7, 8]);
assert.equal(num_updates, 1); assert.equal(num_updates, 1);
assert.deepEqual(container.appended_data.html(), "(6)(8)"); assert.deepEqual($container.$appended_data.html(), "(6)(8)");
}); });
run_test("opts.get_item", () => { run_test("opts.get_item", () => {
@@ -722,12 +722,12 @@ run_test("opts.get_item", () => {
}); });
run_test("render item", () => { run_test("render item", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const INITIAL_RENDER_COUNT = 80; // Keep this in sync with the actual code. const INITIAL_RENDER_COUNT = 80; // Keep this in sync with the actual code.
container.html = () => {}; $container.html = () => {};
let called = false; let called = false;
scroll_container.find = (query) => { $scroll_container.find = (query) => {
const expected_queries = [ const expected_queries = [
`tr[data-item='${INITIAL_RENDER_COUNT}']`, `tr[data-item='${INITIAL_RENDER_COUNT}']`,
`tr[data-item='${INITIAL_RENDER_COUNT - 1}']`, `tr[data-item='${INITIAL_RENDER_COUNT - 1}']`,
@@ -746,7 +746,7 @@ run_test("render item", () => {
replaceWith: (html) => { replaceWith: (html) => {
assert.equal(new_html, html); assert.equal(new_html, html);
called = true; called = true;
container.appended_data.replace(regex, new_html); $container.$appended_data.replace(regex, new_html);
}, },
}; };
}; };
@@ -756,29 +756,29 @@ run_test("render item", () => {
let text = "initial"; let text = "initial";
const get_item = (item) => ({text: `${text}: ${item}`, value: item}); const get_item = (item) => ({text: `${text}: ${item}`, value: item});
const widget = ListWidget.create(container, list, { const widget = ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`, modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`,
get_item, get_item,
html_selector: (item) => `tr[data-item='${item}']`, html_selector: (item) => `tr[data-item='${item}']`,
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
const item = INITIAL_RENDER_COUNT - 1; const item = INITIAL_RENDER_COUNT - 1;
assert.ok(container.appended_data.html().includes("<tr data-item=2>initial: 2</tr>")); assert.ok($container.$appended_data.html().includes("<tr data-item=2>initial: 2</tr>"));
assert.ok(container.appended_data.html().includes("<tr data-item=3>initial: 3</tr>")); assert.ok($container.$appended_data.html().includes("<tr data-item=3>initial: 3</tr>"));
text = "updated"; text = "updated";
called = false; called = false;
widget.render_item(INITIAL_RENDER_COUNT - 1); widget.render_item(INITIAL_RENDER_COUNT - 1);
assert.ok(called); assert.ok(called);
assert.ok(container.appended_data.html().includes("<tr data-item=2>initial: 2</tr>")); assert.ok($container.$appended_data.html().includes("<tr data-item=2>initial: 2</tr>"));
assert.ok( assert.ok(
container.appended_data.html().includes(`<tr data-item=${item}>updated: ${item}</tr>`), $container.$appended_data.html().includes(`<tr data-item=${item}>updated: ${item}</tr>`),
); );
// Item 80 should not be in the rendered list. (0 indexed) // Item 80 should not be in the rendered list. (0 indexed)
assert.ok( assert.ok(
!container.appended_data !$container.$appended_data
.html() .html()
.includes( .includes(
`<tr data-item=${INITIAL_RENDER_COUNT}>initial: ${INITIAL_RENDER_COUNT}</tr>`, `<tr data-item=${INITIAL_RENDER_COUNT}>initial: ${INITIAL_RENDER_COUNT}</tr>`,
@@ -793,24 +793,24 @@ run_test("render item", () => {
// Tests below this are for the corner cases, where we abort the rerender. // Tests below this are for the corner cases, where we abort the rerender.
blueslip.expect("error", "html_selector should be a function."); blueslip.expect("error", "html_selector should be a function.");
ListWidget.create(container, list, { ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`, modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`,
get_item, get_item,
html_selector: "hello world", html_selector: "hello world",
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
blueslip.reset(); blueslip.reset();
let get_item_called; let get_item_called;
const widget_2 = ListWidget.create(container, list, { const widget_2 = ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`, modifier: (item) => `<tr data-item=${item.value}>${item.text}</tr>\n`,
get_item: (item) => { get_item: (item) => {
get_item_called = true; get_item_called = true;
return item; return item;
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
get_item_called = false; get_item_called = false;
widget_2.render_item(item); widget_2.render_item(item);
@@ -818,12 +818,12 @@ run_test("render item", () => {
assert.ok(!get_item_called); assert.ok(!get_item_called);
let rendering_item = false; let rendering_item = false;
const widget_3 = ListWidget.create(container, list, { const widget_3 = ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (item) => (rendering_item ? undefined : `${item}\n`), modifier: (item) => (rendering_item ? undefined : `${item}\n`),
get_item, get_item,
html_selector: (item) => `tr[data-item='${item}']`, html_selector: (item) => `tr[data-item='${item}']`,
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
// Once we have initially rendered the widget, change the // Once we have initially rendered the widget, change the
// behavior of the modifier function. // behavior of the modifier function.
@@ -834,16 +834,16 @@ run_test("render item", () => {
}); });
run_test("Multiselect dropdown retain_selected_items", () => { run_test("Multiselect dropdown retain_selected_items", () => {
const container = make_container(); const $container = make_container();
const scroll_container = make_scroll_container(); const $scroll_container = make_scroll_container();
const filter_element = make_filter_element(); const $filter_element = make_filter_element();
let data_rendered = []; let data_rendered = [];
const list = ["one", "two", "three", "four"].map((x) => ({name: x, value: x})); const list = ["one", "two", "three", "four"].map((x) => ({name: x, value: x}));
const data = ["one"]; // Data initially selected. const data = ["one"]; // Data initially selected.
container.html = () => {}; $container.html = () => {};
container.find = (elem) => DropdownItem(elem); $container.find = (elem) => DropdownItem(elem);
// We essentially create fake jQuery functions // We essentially create fake jQuery functions
// whose return value are stored in objects so that // whose return value are stored in objects so that
@@ -880,8 +880,8 @@ run_test("Multiselect dropdown retain_selected_items", () => {
return ListItem(element, temp); return ListItem(element, temp);
} }
function prepend(data) { function prepend($data) {
temp.prepended_data = data.html(); temp.prepended_data = $data.html();
} }
return { return {
@@ -890,17 +890,17 @@ run_test("Multiselect dropdown retain_selected_items", () => {
}; };
} }
const widget = ListWidget.create(container, list, { const widget = ListWidget.create($container, list, {
name: "replace-list", name: "replace-list",
modifier: (item) => `<li data-value="${item.value}">${item.name}</li>\n`, modifier: (item) => `<li data-value="${item.value}">${item.name}</li>\n`,
multiselect: { multiselect: {
selected_items: data, selected_items: data,
}, },
filter: { filter: {
element: filter_element, $element: $filter_element,
predicate: () => true, predicate: () => true,
}, },
simplebar_container: scroll_container, $simplebar_container: $scroll_container,
}); });
const expected_value = [ const expected_value = [

View File

@@ -117,9 +117,9 @@ run_test("update_messages", () => {
page_params.realm_allow_edit_history = false; page_params.realm_allow_edit_history = false;
message_list.narrowed = "stub-to-ignore"; message_list.narrowed = "stub-to-ignore";
const message_edit_history_modal = $.create("#message-edit-history"); const $message_edit_history_modal = $.create("#message-edit-history");
const modal = $.create("micromodal").addClass("modal--open"); const $modal = $.create("micromodal").addClass("modal--open");
message_edit_history_modal.set_parents_result(".micromodal", modal); $message_edit_history_modal.set_parents_result(".micromodal", $modal);
// TEST THIS: // TEST THIS:
message_events.update_messages(events); message_events.update_messages(events);

View File

@@ -27,47 +27,47 @@ run_test("basics w/progress bar", () => {
let password; let password;
let warning; let warning;
const bar = (function () { const $bar = (function () {
const self = {}; const $self = {};
self.width = (width) => { $self.width = (width) => {
self.w = width; $self.w = width;
return self; return $self;
}; };
self.removeClass = (arg) => { $self.removeClass = (arg) => {
assert.equal(arg, "bar-success bar-danger"); assert.equal(arg, "bar-success bar-danger");
return self; return $self;
}; };
self.addClass = (arg) => { $self.addClass = (arg) => {
self.added_class = arg; $self.added_class = arg;
return self; return $self;
}; };
return self; return $self;
})(); })();
password = "z!X4@S_&"; password = "z!X4@S_&";
accepted = password_quality(password, bar, password_field(10, 80000)); accepted = password_quality(password, $bar, password_field(10, 80000));
assert.ok(!accepted); assert.ok(!accepted);
assert.equal(bar.w, "39.7%"); assert.equal($bar.w, "39.7%");
assert.equal(bar.added_class, "bar-danger"); assert.equal($bar.added_class, "bar-danger");
warning = password_warning(password, password_field(10)); warning = password_warning(password, password_field(10));
assert.equal(warning, "translated: Password should be at least 10 characters long"); assert.equal(warning, "translated: Password should be at least 10 characters long");
password = "foo"; password = "foo";
accepted = password_quality(password, bar, password_field(2, 200)); accepted = password_quality(password, $bar, password_field(2, 200));
assert.ok(accepted); assert.ok(accepted);
assert.equal(bar.w, "10.390277164940581%"); assert.equal($bar.w, "10.390277164940581%");
assert.equal(bar.added_class, "bar-success"); assert.equal($bar.added_class, "bar-success");
warning = password_warning(password, password_field(2)); warning = password_warning(password, password_field(2));
assert.equal(warning, "translated: Password is too weak"); assert.equal(warning, "translated: Password is too weak");
password = "aaaaaaaa"; password = "aaaaaaaa";
accepted = password_quality(password, bar, password_field(6, 1e100)); accepted = password_quality(password, $bar, password_field(6, 1e100));
assert.ok(!accepted); assert.ok(!accepted);
assert.equal(bar.added_class, "bar-danger"); assert.equal($bar.added_class, "bar-danger");
warning = password_warning(password, password_field(6)); warning = password_warning(password, password_field(6));
assert.equal(warning, 'Repeats like "aaa" are easy to guess'); assert.equal(warning, 'Repeats like "aaa" are easy to guess');
}); });

View File

@@ -19,19 +19,19 @@ const user_groups = zrequire("user_groups");
// set global test variables. // set global test variables.
let sort_recipients_called = false; let sort_recipients_called = false;
let sort_streams_called = false; let sort_streams_called = false;
const fake_rendered_person = $.create("fake-rendered-person"); const $fake_rendered_person = $.create("fake-rendered-person");
const fake_rendered_stream = $.create("fake-rendered-stream"); const $fake_rendered_stream = $.create("fake-rendered-stream");
const fake_rendered_group = $.create("fake-rendered-group"); const $fake_rendered_group = $.create("fake-rendered-group");
mock_esm("../../static/js/typeahead_helper", { mock_esm("../../static/js/typeahead_helper", {
render_person() { render_person() {
return fake_rendered_person; return $fake_rendered_person;
}, },
render_user_group() { render_user_group() {
return fake_rendered_group; return $fake_rendered_group;
}, },
render_stream() { render_stream() {
return fake_rendered_stream; return $fake_rendered_stream;
}, },
sort_streams() { sort_streams() {
sort_streams_called = true; sort_streams_called = true;
@@ -113,20 +113,20 @@ run_test("set_up", ({mock_template}) => {
return html; return html;
}); });
let input_pill_typeahead_called = false; let input_pill_typeahead_called = false;
const fake_input = $.create(".input"); const $fake_input = $.create(".input");
fake_input.before = noop; $fake_input.before = noop;
const container = $.create(".pill-container"); const $container = $.create(".pill-container");
container.find = () => fake_input; $container.find = () => $fake_input;
const pill_widget = input_pill.create({ const $pill_widget = input_pill.create({
container, $container,
create_item_from_text: noop, create_item_from_text: noop,
get_text_from_item: noop, get_text_from_item: noop,
}); });
let opts = {}; let opts = {};
fake_input.typeahead = (config) => { $fake_input.typeahead = (config) => {
assert.equal(config.items, 5); assert.equal(config.items, 5);
assert.ok(config.fixed); assert.ok(config.fixed);
assert.ok(config.dropup); assert.ok(config.dropup);
@@ -154,7 +154,7 @@ run_test("set_up", ({mock_template}) => {
// Test stream highlighter for widgets that allow stream pills. // Test stream highlighter for widgets that allow stream pills.
assert.equal( assert.equal(
config.highlighter.call(fake_stream_this, denmark), config.highlighter.call(fake_stream_this, denmark),
fake_rendered_stream, $fake_rendered_stream,
); );
} }
if (opts.user_group && opts.user) { if (opts.user_group && opts.user) {
@@ -162,17 +162,17 @@ run_test("set_up", ({mock_template}) => {
// then we should check that each of them rendered correctly. // then we should check that each of them rendered correctly.
assert.equal( assert.equal(
config.highlighter.call(fake_group_this, testers), config.highlighter.call(fake_group_this, testers),
fake_rendered_group, $fake_rendered_group,
); );
assert.equal(config.highlighter.call(fake_person_this, me), fake_rendered_person); assert.equal(config.highlighter.call(fake_person_this, me), $fake_rendered_person);
} }
if (opts.user && !opts.user_group) { if (opts.user && !opts.user_group) {
assert.equal(config.highlighter.call(fake_person_this, me), fake_rendered_person); assert.equal(config.highlighter.call(fake_person_this, me), $fake_rendered_person);
} }
if (!opts.user && opts.user_group) { if (!opts.user && opts.user_group) {
assert.equal( assert.equal(
config.highlighter.call(fake_group_this, testers), config.highlighter.call(fake_group_this, testers),
fake_rendered_group, $fake_rendered_group,
); );
} }
})(); })();
@@ -288,7 +288,7 @@ run_test("set_up", ({mock_template}) => {
// updater in pill_typeahead. // updater in pill_typeahead.
function number_of_pills() { function number_of_pills() {
const pills = pill_widget.items(); const pills = $pill_widget.items();
return pills.length; return pills.length;
} }
assert.equal(number_of_pills(), 0); assert.equal(number_of_pills(), 0);
@@ -307,7 +307,7 @@ run_test("set_up", ({mock_template}) => {
}; };
function test_pill_typeahead(opts) { function test_pill_typeahead(opts) {
pill_typeahead.set_up(fake_input, pill_widget, opts); pill_typeahead.set_up($fake_input, $pill_widget, opts);
assert.ok(input_pill_typeahead_called); assert.ok(input_pill_typeahead_called);
} }
@@ -339,6 +339,6 @@ run_test("set_up", ({mock_template}) => {
opts = {}; opts = {};
input_pill_typeahead_called = false; input_pill_typeahead_called = false;
blueslip.expect("error", "Unspecified possible item types"); blueslip.expect("error", "Unspecified possible item types");
pill_typeahead.set_up(fake_input, pill_widget, {}); pill_typeahead.set_up($fake_input, $pill_widget, {});
assert.ok(!input_pill_typeahead_called); assert.ok(!input_pill_typeahead_called);
}); });

View File

@@ -16,23 +16,23 @@ run_test("update_dom_with_unread_counts", () => {
narrow_state.set_current_filter("stub"); narrow_state.set_current_filter("stub");
assert.equal(narrow_state.active(), true); assert.equal(narrow_state.active(), true);
const total_count = $.create("total-count-stub"); const $total_count = $.create("total-count-stub");
const private_li = $(".top_left_private_messages .private_messages_header"); const $private_li = $(".top_left_private_messages .private_messages_header");
private_li.set_find_results(".unread_count", total_count); $private_li.set_find_results(".unread_count", $total_count);
counts = { counts = {
private_message_count: 10, private_message_count: 10,
}; };
pm_list.update_dom_with_unread_counts(counts); pm_list.update_dom_with_unread_counts(counts);
assert.equal(total_count.text(), "10"); assert.equal($total_count.text(), "10");
assert.ok(total_count.visible()); assert.ok($total_count.visible());
counts = { counts = {
private_message_count: 0, private_message_count: 0,
}; };
pm_list.update_dom_with_unread_counts(counts); pm_list.update_dom_with_unread_counts(counts);
assert.equal(total_count.text(), ""); assert.equal($total_count.text(), "");
assert.ok(!total_count.visible()); assert.ok(!$total_count.visible());
}); });

View File

@@ -210,7 +210,7 @@ run_test("activate another person poll", ({mock_template}) => {
mock_template("widgets/poll_widget.hbs", false, () => "widgets/poll_widget"); mock_template("widgets/poll_widget.hbs", false, () => "widgets/poll_widget");
mock_template("widgets/poll_widget_results.hbs", false, () => "widgets/poll_widget_results"); mock_template("widgets/poll_widget_results.hbs", false, () => "widgets/poll_widget_results");
const widget_elem = $("<div>").addClass("widget-content"); const $widget_elem = $("<div>").addClass("widget-content");
let out_data; // Used to check the event data sent to the server let out_data; // Used to check the event data sent to the server
const callback = (data) => { const callback = (data) => {
@@ -218,7 +218,7 @@ run_test("activate another person poll", ({mock_template}) => {
}; };
const opts = { const opts = {
elem: widget_elem, $elem: $widget_elem,
callback, callback,
message: { message: {
sender_id: alice.user_id, sender_id: alice.user_id,
@@ -229,53 +229,53 @@ run_test("activate another person poll", ({mock_template}) => {
}; };
const set_widget_find_result = (selector) => { const set_widget_find_result = (selector) => {
const elem = $.create(selector); const $elem = $.create(selector);
widget_elem.set_find_results(selector, elem); $widget_elem.set_find_results(selector, $elem);
return elem; return $elem;
}; };
const poll_option = set_widget_find_result("button.poll-option"); const $poll_option = set_widget_find_result("button.poll-option");
const poll_option_input = set_widget_find_result("input.poll-option"); const $poll_option_input = set_widget_find_result("input.poll-option");
const widget_option_container = set_widget_find_result("ul.poll-widget"); const $widget_option_container = set_widget_find_result("ul.poll-widget");
const poll_question_submit = set_widget_find_result("button.poll-question-check"); const $poll_question_submit = set_widget_find_result("button.poll-question-check");
const poll_edit_question = set_widget_find_result(".poll-edit-question"); const $poll_edit_question = set_widget_find_result(".poll-edit-question");
const poll_question_header = set_widget_find_result(".poll-question-header"); const $poll_question_header = set_widget_find_result(".poll-question-header");
const poll_question_container = set_widget_find_result(".poll-question-bar"); const $poll_question_container = set_widget_find_result(".poll-question-bar");
const poll_option_container = set_widget_find_result(".poll-option-bar"); const $poll_option_container = set_widget_find_result(".poll-option-bar");
const poll_vote_button = set_widget_find_result("button.poll-vote"); const $poll_vote_button = set_widget_find_result("button.poll-vote");
const poll_please_wait = set_widget_find_result(".poll-please-wait"); const $poll_please_wait = set_widget_find_result(".poll-please-wait");
const poll_author_help = set_widget_find_result(".poll-author-help"); const $poll_author_help = set_widget_find_result(".poll-author-help");
set_widget_find_result("button.poll-question-remove"); set_widget_find_result("button.poll-question-remove");
set_widget_find_result("input.poll-question"); set_widget_find_result("input.poll-question");
poll_widget.activate(opts); poll_widget.activate(opts);
assert.ok(poll_option_container.visible()); assert.ok($poll_option_container.visible());
assert.ok(poll_question_header.visible()); assert.ok($poll_question_header.visible());
assert.ok(!poll_question_container.visible()); assert.ok(!$poll_question_container.visible());
assert.ok(!poll_question_submit.visible()); assert.ok(!$poll_question_submit.visible());
assert.ok(!poll_edit_question.visible()); assert.ok(!$poll_edit_question.visible());
assert.ok(!poll_please_wait.visible()); assert.ok(!$poll_please_wait.visible());
assert.ok(!poll_author_help.visible()); assert.ok(!$poll_author_help.visible());
assert.equal(widget_elem.html(), "widgets/poll_widget"); assert.equal($widget_elem.html(), "widgets/poll_widget");
assert.equal(widget_option_container.html(), "widgets/poll_widget_results"); assert.equal($widget_option_container.html(), "widgets/poll_widget_results");
assert.equal(poll_question_header.text(), "What do you want?"); assert.equal($poll_question_header.text(), "What do you want?");
{ {
/* Testing data sent to server on adding option */ /* Testing data sent to server on adding option */
poll_option_input.val("cool choice"); $poll_option_input.val("cool choice");
out_data = undefined; out_data = undefined;
poll_option.trigger("click"); $poll_option.trigger("click");
assert.deepEqual(out_data, {type: "new_option", idx: 1, option: "cool choice"}); assert.deepEqual(out_data, {type: "new_option", idx: 1, option: "cool choice"});
poll_option_input.val(""); $poll_option_input.val("");
out_data = undefined; out_data = undefined;
poll_option.trigger("click"); $poll_option.trigger("click");
assert.deepEqual(out_data, undefined); assert.deepEqual(out_data, undefined);
} }
@@ -298,13 +298,13 @@ run_test("activate another person poll", ({mock_template}) => {
}, },
]; ];
widget_elem.handle_events(vote_events); $widget_elem.handle_events(vote_events);
{ {
/* Testing data sent to server on voting */ /* Testing data sent to server on voting */
poll_vote_button.attr("data-key", "100,1"); $poll_vote_button.attr("data-key", "100,1");
out_data = undefined; out_data = undefined;
poll_vote_button.trigger("click"); $poll_vote_button.trigger("click");
assert.deepEqual(out_data, {type: "vote", key: "100,1", vote: 1}); assert.deepEqual(out_data, {type: "vote", key: "100,1", vote: 1});
} }
@@ -318,20 +318,20 @@ run_test("activate another person poll", ({mock_template}) => {
}, },
]; ];
widget_elem.handle_events(add_question_event); $widget_elem.handle_events(add_question_event);
}); });
run_test("activate own poll", ({mock_template}) => { run_test("activate own poll", ({mock_template}) => {
mock_template("widgets/poll_widget.hbs", false, () => "widgets/poll_widget"); mock_template("widgets/poll_widget.hbs", false, () => "widgets/poll_widget");
mock_template("widgets/poll_widget_results.hbs", false, () => "widgets/poll_widget_results"); mock_template("widgets/poll_widget_results.hbs", false, () => "widgets/poll_widget_results");
const widget_elem = $("<div>").addClass("widget-content"); const $widget_elem = $("<div>").addClass("widget-content");
let out_data; let out_data;
const callback = (data) => { const callback = (data) => {
out_data = data; out_data = data;
}; };
const opts = { const opts = {
elem: widget_elem, $elem: $widget_elem,
callback, callback,
message: { message: {
sender_id: me.user_id, sender_id: me.user_id,
@@ -342,59 +342,59 @@ run_test("activate own poll", ({mock_template}) => {
}; };
const set_widget_find_result = (selector) => { const set_widget_find_result = (selector) => {
const elem = $.create(selector); const $elem = $.create(selector);
widget_elem.set_find_results(selector, elem); $widget_elem.set_find_results(selector, $elem);
return elem; return $elem;
}; };
set_widget_find_result("button.poll-option"); set_widget_find_result("button.poll-option");
const poll_option_input = set_widget_find_result("input.poll-option"); const $poll_option_input = set_widget_find_result("input.poll-option");
const widget_option_container = set_widget_find_result("ul.poll-widget"); const $widget_option_container = set_widget_find_result("ul.poll-widget");
const poll_question_submit = set_widget_find_result("button.poll-question-check"); const $poll_question_submit = set_widget_find_result("button.poll-question-check");
const poll_edit_question = set_widget_find_result(".poll-edit-question"); const $poll_edit_question = set_widget_find_result(".poll-edit-question");
const poll_question_input = set_widget_find_result("input.poll-question"); const $poll_question_input = set_widget_find_result("input.poll-question");
const poll_question_header = set_widget_find_result(".poll-question-header"); const $poll_question_header = set_widget_find_result(".poll-question-header");
const poll_question_container = set_widget_find_result(".poll-question-bar"); const $poll_question_container = set_widget_find_result(".poll-question-bar");
const poll_option_container = set_widget_find_result(".poll-option-bar"); const $poll_option_container = set_widget_find_result(".poll-option-bar");
set_widget_find_result("button.poll-vote"); set_widget_find_result("button.poll-vote");
const poll_please_wait = set_widget_find_result(".poll-please-wait"); const $poll_please_wait = set_widget_find_result(".poll-please-wait");
const poll_author_help = set_widget_find_result(".poll-author-help"); const $poll_author_help = set_widget_find_result(".poll-author-help");
set_widget_find_result("button.poll-question-remove"); set_widget_find_result("button.poll-question-remove");
function assert_visibility() { function assert_visibility() {
assert.ok(poll_option_container.visible()); assert.ok($poll_option_container.visible());
assert.ok(poll_question_header.visible()); assert.ok($poll_question_header.visible());
assert.ok(!poll_question_container.visible()); assert.ok(!$poll_question_container.visible());
assert.ok(poll_edit_question.visible()); assert.ok($poll_edit_question.visible());
assert.ok(!poll_please_wait.visible()); assert.ok(!$poll_please_wait.visible());
assert.ok(!poll_author_help.visible()); assert.ok(!$poll_author_help.visible());
} }
poll_widget.activate(opts); poll_widget.activate(opts);
assert_visibility(); assert_visibility();
assert.ok(!poll_question_submit.visible()); assert.ok(!$poll_question_submit.visible());
assert.equal(widget_elem.html(), "widgets/poll_widget"); assert.equal($widget_elem.html(), "widgets/poll_widget");
assert.equal(widget_option_container.html(), "widgets/poll_widget_results"); assert.equal($widget_option_container.html(), "widgets/poll_widget_results");
assert.equal(poll_question_header.text(), "Where to go?"); assert.equal($poll_question_header.text(), "Where to go?");
{ {
/* Testing data sent to server on editing question */ /* Testing data sent to server on editing question */
poll_question_input.val("Is it new?"); $poll_question_input.val("Is it new?");
out_data = undefined; out_data = undefined;
poll_question_submit.trigger("click"); $poll_question_submit.trigger("click");
assert.deepEqual(out_data, {type: "question", question: "Is it new?"}); assert.deepEqual(out_data, {type: "question", question: "Is it new?"});
assert_visibility(); assert_visibility();
assert.ok(poll_question_submit.visible()); assert.ok($poll_question_submit.visible());
poll_option_input.val(""); $poll_option_input.val("");
out_data = undefined; out_data = undefined;
poll_question_submit.trigger("click"); $poll_question_submit.trigger("click");
assert.deepEqual(out_data, undefined); assert.deepEqual(out_data, undefined);
} }
}); });

View File

@@ -146,9 +146,9 @@ test_ui("sender_hover", ({override, mock_template}) => {
assert.equal(msg_id, message.id); assert.equal(msg_id, message.id);
}; };
const target = $.create("click target"); const $target = $.create("click target");
target.closest = (sel) => { $target.closest = (sel) => {
assert.equal(sel, ".message_row"); assert.equal(sel, ".message_row");
return {}; return {};
}; };
@@ -205,7 +205,7 @@ test_ui("sender_hover", ({override, mock_template}) => {
$.create(".user_popover_email", {children: []}); $.create(".user_popover_email", {children: []});
const image_stubber = make_image_stubber(); const image_stubber = make_image_stubber();
handler.call(target, e); handler.call($target, e);
const avatar_img = image_stubber.get(0); const avatar_img = image_stubber.get(0);
assert.equal(avatar_img.src.toString(), "/avatar/42/medium"); assert.equal(avatar_img.src.toString(), "/avatar/42/medium");
@@ -216,7 +216,7 @@ test_ui("sender_hover", ({override, mock_template}) => {
test_ui("actions_popover", ({override, override_rewire, mock_template}) => { test_ui("actions_popover", ({override, override_rewire, mock_template}) => {
override($.fn, "popover", noop); override($.fn, "popover", noop);
const target = $.create("click target"); const $target = $.create("click target");
const handler = $("#main_div").get_on_handler("click", ".actions_hover"); const handler = $("#main_div").get_on_handler("click", ".actions_hover");
@@ -241,7 +241,7 @@ test_ui("actions_popover", ({override, override_rewire, mock_template}) => {
override_rewire(message_edit, "get_editability", () => 4); override_rewire(message_edit, "get_editability", () => 4);
target.closest = (sel) => { $target.closest = (sel) => {
assert.equal(sel, ".message_row"); assert.equal(sel, ".message_row");
return { return {
toggleClass: noop, toggleClass: noop,
@@ -257,5 +257,5 @@ test_ui("actions_popover", ({override, override_rewire, mock_template}) => {
return "actions-content"; return "actions-content";
}); });
handler.call(target, e); handler.call($target, e);
}); });

View File

@@ -361,46 +361,46 @@ test("sending", ({override, override_rewire}) => {
}); });
test("set_reaction_count", () => { test("set_reaction_count", () => {
const count_element = $.create("count-stub"); const $count_element = $.create("count-stub");
const reaction_element = $.create("reaction-stub"); const $reaction_element = $.create("reaction-stub");
reaction_element.set_find_results(".message_reaction_count", count_element); $reaction_element.set_find_results(".message_reaction_count", $count_element);
reactions.set_reaction_count(reaction_element, 5); reactions.set_reaction_count($reaction_element, 5);
assert.equal(count_element.text(), "5"); assert.equal($count_element.text(), "5");
}); });
test("find_reaction", ({override_rewire}) => { test("find_reaction", ({override_rewire}) => {
const message_id = 99; const message_id = 99;
const local_id = "unicode_emoji,1f44b"; const local_id = "unicode_emoji,1f44b";
const reaction_section = $.create("section-stub"); const $reaction_section = $.create("section-stub");
const reaction_stub = "reaction-stub"; const reaction_stub = "reaction-stub";
reaction_section.set_find_results( $reaction_section.set_find_results(
`[data-reaction-id='${CSS.escape(local_id)}']`, `[data-reaction-id='${CSS.escape(local_id)}']`,
reaction_stub, reaction_stub,
); );
override_rewire(reactions, "get_reaction_section", (arg) => { override_rewire(reactions, "get_reaction_section", (arg) => {
assert.equal(arg, message_id); assert.equal(arg, message_id);
return reaction_section; return $reaction_section;
}); });
assert.equal(reactions.find_reaction(message_id, local_id), reaction_stub); assert.equal(reactions.find_reaction(message_id, local_id), reaction_stub);
}); });
test("get_reaction_section", () => { test("get_reaction_section", () => {
const message_table = $.create(".message_table"); const $message_table = $.create(".message_table");
const message_row = $.create("some-message-row"); const $message_row = $.create("some-message-row");
const message_reactions = $.create("our-reactions-section"); const $message_reactions = $.create("our-reactions-section");
message_table.set_find_results(`[zid='${CSS.escape(555)}']`, message_row); $message_table.set_find_results(`[zid='${CSS.escape(555)}']`, $message_row);
message_row.set_find_results(".message_reactions", message_reactions); $message_row.set_find_results(".message_reactions", $message_reactions);
const section = reactions.get_reaction_section(555); const section = reactions.get_reaction_section(555);
assert.equal(section, message_reactions); assert.equal(section, $message_reactions);
}); });
test("emoji_reaction_title", ({override}) => { test("emoji_reaction_title", ({override}) => {
@@ -599,14 +599,14 @@ test("view.insert_new_reaction (me w/unicode emoji)", ({override_rewire, mock_te
user_id: alice.user_id, user_id: alice.user_id,
}; };
const message_reactions = $.create("our-reactions"); const $message_reactions = $.create("our-reactions");
override_rewire(reactions, "get_reaction_section", (message_id) => { override_rewire(reactions, "get_reaction_section", (message_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
return message_reactions; return $message_reactions;
}); });
message_reactions.find = (selector) => { $message_reactions.find = (selector) => {
assert.equal(selector, ".reaction_button"); assert.equal(selector, ".reaction_button");
return "reaction-button-stub"; return "reaction-button-stub";
}; };
@@ -646,14 +646,14 @@ test("view.insert_new_reaction (them w/zulip emoji)", ({override_rewire, mock_te
user_id: bob.user_id, user_id: bob.user_id,
}; };
const message_reactions = $.create("our-reactions"); const $message_reactions = $.create("our-reactions");
override_rewire(reactions, "get_reaction_section", (message_id) => { override_rewire(reactions, "get_reaction_section", (message_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
return message_reactions; return $message_reactions;
}); });
message_reactions.find = (selector) => { $message_reactions.find = (selector) => {
assert.equal(selector, ".reaction_button"); assert.equal(selector, ".reaction_button");
return "reaction-button-stub"; return "reaction-button-stub";
}; };
@@ -696,24 +696,24 @@ test("view.update_existing_reaction (me)", ({override_rewire}) => {
user_list: [alice.user_id, bob.user_id], user_list: [alice.user_id, bob.user_id],
}; };
const our_reaction = $.create("our-reaction-stub"); const $our_reaction = $.create("our-reaction-stub");
override_rewire(reactions, "find_reaction", (message_id, local_id) => { override_rewire(reactions, "find_reaction", (message_id, local_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
assert.equal(local_id, "unicode_emoji,1f3b1"); assert.equal(local_id, "unicode_emoji,1f3b1");
return our_reaction; return $our_reaction;
}); });
override_rewire(reactions, "set_reaction_count", (reaction, count) => { override_rewire(reactions, "set_reaction_count", (reaction, count) => {
assert.equal(reaction, our_reaction); assert.equal(reaction, $our_reaction);
assert.equal(count, 2); assert.equal(count, 2);
}); });
reactions.view.update_existing_reaction(opts); reactions.view.update_existing_reaction(opts);
assert.ok(our_reaction.hasClass("reacted")); assert.ok($our_reaction.hasClass("reacted"));
assert.equal( assert.equal(
our_reaction.attr("aria-label"), $our_reaction.attr("aria-label"),
"translated: You (click to remove) and Bob van Roberts reacted with :8ball:", "translated: You (click to remove) and Bob van Roberts reacted with :8ball:",
); );
}); });
@@ -728,24 +728,24 @@ test("view.update_existing_reaction (them)", ({override_rewire}) => {
user_list: [alice.user_id, bob.user_id, cali.user_id, alexus.user_id], user_list: [alice.user_id, bob.user_id, cali.user_id, alexus.user_id],
}; };
const our_reaction = $.create("our-reaction-stub"); const $our_reaction = $.create("our-reaction-stub");
override_rewire(reactions, "find_reaction", (message_id, local_id) => { override_rewire(reactions, "find_reaction", (message_id, local_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
assert.equal(local_id, "unicode_emoji,1f3b1"); assert.equal(local_id, "unicode_emoji,1f3b1");
return our_reaction; return $our_reaction;
}); });
override_rewire(reactions, "set_reaction_count", (reaction, count) => { override_rewire(reactions, "set_reaction_count", (reaction, count) => {
assert.equal(reaction, our_reaction); assert.equal(reaction, $our_reaction);
assert.equal(count, 4); assert.equal(count, 4);
}); });
reactions.view.update_existing_reaction(opts); reactions.view.update_existing_reaction(opts);
assert.ok(!our_reaction.hasClass("reacted")); assert.ok(!$our_reaction.hasClass("reacted"));
assert.equal( assert.equal(
our_reaction.attr("aria-label"), $our_reaction.attr("aria-label"),
"translated: You (click to remove), Bob van Roberts, Cali and Alexus reacted with :8ball:", "translated: You (click to remove), Bob van Roberts, Cali and Alexus reacted with :8ball:",
); );
}); });
@@ -760,25 +760,25 @@ test("view.remove_reaction (me)", ({override_rewire}) => {
user_list: [bob.user_id, cali.user_id], user_list: [bob.user_id, cali.user_id],
}; };
const our_reaction = $.create("our-reaction-stub"); const $our_reaction = $.create("our-reaction-stub");
our_reaction.addClass("reacted"); $our_reaction.addClass("reacted");
override_rewire(reactions, "find_reaction", (message_id, local_id) => { override_rewire(reactions, "find_reaction", (message_id, local_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
assert.equal(local_id, "unicode_emoji,1f3b1"); assert.equal(local_id, "unicode_emoji,1f3b1");
return our_reaction; return $our_reaction;
}); });
override_rewire(reactions, "set_reaction_count", (reaction, count) => { override_rewire(reactions, "set_reaction_count", (reaction, count) => {
assert.equal(reaction, our_reaction); assert.equal(reaction, $our_reaction);
assert.equal(count, 2); assert.equal(count, 2);
}); });
reactions.view.remove_reaction(opts); reactions.view.remove_reaction(opts);
assert.ok(!our_reaction.hasClass("reacted")); assert.ok(!$our_reaction.hasClass("reacted"));
assert.equal( assert.equal(
our_reaction.attr("aria-label"), $our_reaction.attr("aria-label"),
"translated: Bob van Roberts and Cali reacted with :8ball:", "translated: Bob van Roberts and Cali reacted with :8ball:",
); );
}); });
@@ -793,26 +793,26 @@ test("view.remove_reaction (them)", ({override_rewire}) => {
user_list: [alice.user_id], user_list: [alice.user_id],
}; };
const our_reaction = $.create("our-reaction-stub"); const $our_reaction = $.create("our-reaction-stub");
our_reaction.addClass("reacted"); $our_reaction.addClass("reacted");
override_rewire(reactions, "find_reaction", (message_id, local_id) => { override_rewire(reactions, "find_reaction", (message_id, local_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
assert.equal(local_id, "unicode_emoji,1f3b1"); assert.equal(local_id, "unicode_emoji,1f3b1");
return our_reaction; return $our_reaction;
}); });
override_rewire(reactions, "set_reaction_count", (reaction, count) => { override_rewire(reactions, "set_reaction_count", (reaction, count) => {
assert.equal(reaction, our_reaction); assert.equal(reaction, $our_reaction);
assert.equal(count, 1); assert.equal(count, 1);
}); });
our_reaction.addClass("reacted"); $our_reaction.addClass("reacted");
reactions.view.remove_reaction(opts); reactions.view.remove_reaction(opts);
assert.ok(our_reaction.hasClass("reacted")); assert.ok($our_reaction.hasClass("reacted"));
assert.equal( assert.equal(
our_reaction.attr("aria-label"), $our_reaction.attr("aria-label"),
"translated: You (click to remove) reacted with :8ball:", "translated: You (click to remove) reacted with :8ball:",
); );
}); });
@@ -827,16 +827,16 @@ test("view.remove_reaction (last person)", ({override_rewire}) => {
user_list: [], user_list: [],
}; };
const our_reaction = $.create("our-reaction-stub"); const $our_reaction = $.create("our-reaction-stub");
override_rewire(reactions, "find_reaction", (message_id, local_id) => { override_rewire(reactions, "find_reaction", (message_id, local_id) => {
assert.equal(message_id, opts.message_id); assert.equal(message_id, opts.message_id);
assert.equal(local_id, "unicode_emoji,1f3b1"); assert.equal(local_id, "unicode_emoji,1f3b1");
return our_reaction; return $our_reaction;
}); });
let removed; let removed;
our_reaction.remove = () => { $our_reaction.remove = () => {
removed = true; removed = true;
}; };
reactions.view.remove_reaction(opts); reactions.view.remove_reaction(opts);

View File

@@ -323,9 +323,9 @@ function stub_out_filter_buttons() {
// See show_selected_filters() and set_filter() in the // See show_selected_filters() and set_filter() in the
// implementation. // implementation.
for (const filter of ["all", "unread", "muted", "participated"]) { for (const filter of ["all", "unread", "muted", "participated"]) {
const stub = $.create(`filter-${filter}-stub`); const $stub = $.create(`filter-${filter}-stub`);
const selector = `[data-filter="${filter}"]`; const selector = `[data-filter="${filter}"]`;
$("#recent_topics_filter_buttons").set_find_results(selector, stub); $("#recent_topics_filter_buttons").set_find_results(selector, $stub);
} }
} }

View File

@@ -104,12 +104,12 @@ const get_content_element = () => {
}; };
run_test("misc_helpers", () => { run_test("misc_helpers", () => {
const elem = $.create("user-mention"); const $elem = $.create("user-mention");
rm.set_name_in_mention_element(elem, "Aaron"); rm.set_name_in_mention_element($elem, "Aaron");
assert.equal(elem.text(), "@Aaron"); assert.equal($elem.text(), "@Aaron");
elem.addClass("silent"); $elem.addClass("silent");
rm.set_name_in_mention_element(elem, "Aaron, but silent"); rm.set_name_in_mention_element($elem, "Aaron, but silent");
assert.equal(elem.text(), "Aaron, but silent"); assert.equal($elem.text(), "Aaron, but silent");
}); });
run_test("user-mention", () => { run_test("user-mention", () => {
@@ -423,8 +423,8 @@ function test_code_playground(mock_template, viewing_code) {
return { return {
prepends, prepends,
copy_code: $copy_code_button, $copy_code: $copy_code_button,
view_code: $view_code_in_playground, $view_code: $view_code_in_playground,
}; };
} }
@@ -434,12 +434,12 @@ run_test("code playground none", ({override, mock_template}) => {
return undefined; return undefined;
}); });
const {prepends, copy_code, view_code} = test_code_playground(mock_template, false); const {prepends, $copy_code, $view_code} = test_code_playground(mock_template, false);
assert.deepEqual(prepends, [copy_code]); assert.deepEqual(prepends, [$copy_code]);
assert_clipboard_setup(); assert_clipboard_setup();
assert.equal(view_code.attr("data-tippy-content"), undefined); assert.equal($view_code.attr("data-tippy-content"), undefined);
assert.equal(view_code.attr("aria-label"), undefined); assert.equal($view_code.attr("aria-label"), undefined);
}); });
run_test("code playground single", ({override, mock_template}) => { run_test("code playground single", ({override, mock_template}) => {
@@ -448,16 +448,16 @@ run_test("code playground single", ({override, mock_template}) => {
return [{name: "Some Javascript Playground"}]; return [{name: "Some Javascript Playground"}];
}); });
const {prepends, copy_code, view_code} = test_code_playground(mock_template, true); const {prepends, $copy_code, $view_code} = test_code_playground(mock_template, true);
assert.deepEqual(prepends, [view_code, copy_code]); assert.deepEqual(prepends, [$view_code, $copy_code]);
assert_clipboard_setup(); assert_clipboard_setup();
assert.equal( assert.equal(
view_code.attr("data-tippy-content"), $view_code.attr("data-tippy-content"),
"translated: View in Some Javascript Playground", "translated: View in Some Javascript Playground",
); );
assert.equal(view_code.attr("aria-label"), "translated: View in Some Javascript Playground"); assert.equal($view_code.attr("aria-label"), "translated: View in Some Javascript Playground");
assert.equal(view_code.attr("aria-haspopup"), undefined); assert.equal($view_code.attr("aria-haspopup"), undefined);
}); });
run_test("code playground multiple", ({override, mock_template}) => { run_test("code playground multiple", ({override, mock_template}) => {
@@ -466,13 +466,13 @@ run_test("code playground multiple", ({override, mock_template}) => {
return ["whatever", "whatever"]; return ["whatever", "whatever"];
}); });
const {prepends, copy_code, view_code} = test_code_playground(mock_template, true); const {prepends, $copy_code, $view_code} = test_code_playground(mock_template, true);
assert.deepEqual(prepends, [view_code, copy_code]); assert.deepEqual(prepends, [$view_code, $copy_code]);
assert_clipboard_setup(); assert_clipboard_setup();
assert.equal(view_code.attr("data-tippy-content"), "translated: View in playground"); assert.equal($view_code.attr("data-tippy-content"), "translated: View in playground");
assert.equal(view_code.attr("aria-label"), "translated: View in playground"); assert.equal($view_code.attr("aria-label"), "translated: View in playground");
assert.equal(view_code.attr("aria-haspopup"), "true"); assert.equal($view_code.attr("aria-haspopup"), "true");
}); });
run_test("rtl", () => { run_test("rtl", () => {

View File

@@ -129,20 +129,20 @@ run_test("get_direction", () => {
}); });
run_test("set_rtl_class_for_textarea rtl", () => { run_test("set_rtl_class_for_textarea rtl", () => {
const textarea = $.create("some-textarea"); const $textarea = $.create("some-textarea");
assert.ok(!textarea.hasClass("rtl")); assert.ok(!$textarea.hasClass("rtl"));
const text = "```quote\nمرحبا"; const text = "```quote\nمرحبا";
textarea.val(text); $textarea.val(text);
rtl.set_rtl_class_for_textarea(textarea); rtl.set_rtl_class_for_textarea($textarea);
assert.ok(textarea.hasClass("rtl")); assert.ok($textarea.hasClass("rtl"));
}); });
run_test("set_rtl_class_for_textarea ltr", () => { run_test("set_rtl_class_for_textarea ltr", () => {
const textarea = $.create("some-textarea"); const $textarea = $.create("some-textarea");
textarea.addClass("rtl"); $textarea.addClass("rtl");
assert.ok(textarea.hasClass("rtl")); assert.ok($textarea.hasClass("rtl"));
const text = "```quote\nEnglish text"; const text = "```quote\nEnglish text";
textarea.val(text); $textarea.val(text);
rtl.set_rtl_class_for_textarea(textarea); rtl.set_rtl_class_for_textarea($textarea);
assert.ok(!textarea.hasClass("rtl")); assert.ok(!$textarea.hasClass("rtl"));
}); });

View File

@@ -89,7 +89,7 @@ run_test("scroll_delta", () => {
}); });
run_test("scroll_element_into_container", () => { run_test("scroll_element_into_container", () => {
const container = (function () { const $container = (function () {
let top = 3; let top = 3;
return { return {
height: () => 100, height: () => 100,
@@ -103,21 +103,21 @@ run_test("scroll_element_into_container", () => {
}; };
})(); })();
const elem1 = { const $elem1 = {
innerHeight: () => 25, innerHeight: () => 25,
position: () => ({ position: () => ({
top: 0, top: 0,
}), }),
}; };
scroll_util.scroll_element_into_container(elem1, container); scroll_util.scroll_element_into_container($elem1, $container);
assert.equal(container.scrollTop(), 3); assert.equal($container.scrollTop(), 3);
const elem2 = { const $elem2 = {
innerHeight: () => 15, innerHeight: () => 15,
position: () => ({ position: () => ({
top: 250, top: 250,
}), }),
}; };
scroll_util.scroll_element_into_container(elem2, container); scroll_util.scroll_element_into_container($elem2, $container);
assert.equal(container.scrollTop(), 250 - 100 + 3 + 15); assert.equal($container.scrollTop(), 250 - 100 + 3 + 15);
}); });

View File

@@ -51,50 +51,50 @@ test("clear_search_form", () => {
}); });
test("update_button_visibility", () => { test("update_button_visibility", () => {
const search_query = $("#search_query"); const $search_query = $("#search_query");
const search_button = $(".search_button"); const $search_button = $(".search_button");
search_query.is = () => false; $search_query.is = () => false;
search_query.val(""); $search_query.val("");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(search_button.prop("disabled")); assert.ok($search_button.prop("disabled"));
search_query.is = () => true; $search_query.is = () => true;
search_query.val(""); $search_query.val("");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_query.is = () => false; $search_query.is = () => false;
search_query.val("Test search term"); $search_query.val("Test search term");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_query.is = () => false; $search_query.is = () => false;
search_query.val(""); $search_query.val("");
narrow_state.active = () => true; narrow_state.active = () => true;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
}); });
test("initialize", () => { test("initialize", () => {
const search_query_box = $("#search_query"); const $search_query_box = $("#search_query");
const searchbox_form = $("#searchbox_form"); const $searchbox_form = $("#searchbox_form");
const search_button = $(".search_button"); const $search_button = $(".search_button");
const searchbox = $("#searchbox"); const $searchbox = $("#searchbox");
search_query_box[0] = "stub"; $search_query_box[0] = "stub";
search_pill.get_search_string_for_current_filter = () => "is:starred"; search_pill.get_search_string_for_current_filter = () => "is:starred";
search_suggestion.max_num_of_search_results = 99; search_suggestion.max_num_of_search_results = 99;
search_query_box.typeahead = (opts) => { $search_query_box.typeahead = (opts) => {
assert.equal(opts.fixed, true); assert.equal(opts.fixed, true);
assert.equal(opts.items, 99); assert.equal(opts.items, 99);
assert.equal(opts.naturalSearch, true); assert.equal(opts.naturalSearch, true);
@@ -144,7 +144,7 @@ test("initialize", () => {
let operators; let operators;
let is_blurred; let is_blurred;
let is_append_search_string_called; let is_append_search_string_called;
search_query_box.on("blur", () => { $search_query_box.on("blur", () => {
is_blurred = true; is_blurred = true;
}); });
search_pill.append_search_string = () => { search_pill.append_search_string = () => {
@@ -154,7 +154,7 @@ test("initialize", () => {
const _setup = (search_box_val) => { const _setup = (search_box_val) => {
is_blurred = false; is_blurred = false;
is_append_search_string_called = false; is_append_search_string_called = false;
search_query_box.val(search_box_val); $search_query_box.val(search_box_val);
Filter.parse = (search_string) => { Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val); assert.equal(search_string, search_box_val);
return operators; return operators;
@@ -199,34 +199,35 @@ test("initialize", () => {
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(is_append_search_string_called); assert.ok(is_append_search_string_called);
search_query_box.off("blur"); $search_query_box.off("blur");
} }
}; };
search.initialize(); search.initialize();
const search_pill_stub = $.create(".pill"); const $search_pill_stub = $.create(".pill");
search_pill_stub.closest = () => ({data: noop}); $search_pill_stub.closest = () => ({data: noop});
const stub_event = { const stub_event = {
relatedTarget: search_pill_stub, // FIXME: event.relatedTarget should not be a jQuery object
relatedTarget: $search_pill_stub,
}; };
search_query_box.val("test string"); $search_query_box.val("test string");
narrow_state.search_string = () => "ver"; narrow_state.search_string = () => "ver";
search_query_box.trigger(new $.Event("blur", stub_event)); $search_query_box.trigger(new $.Event("blur", stub_event));
assert.equal(search_query_box.val(), "test string"); assert.equal($search_query_box.val(), "test string");
let css_args; let css_args;
searchbox.css = (args) => { $searchbox.css = (args) => {
css_args = args; css_args = args;
}; };
searchbox.trigger("focusout"); $searchbox.trigger("focusout");
assert.deepEqual(css_args, {"box-shadow": "unset"}); assert.deepEqual(css_args, {"box-shadow": "unset"});
search.__Rewire__("is_using_input_method", false); search.__Rewire__("is_using_input_method", false);
searchbox_form.trigger("compositionend"); $searchbox_form.trigger("compositionend");
assert.ok(search.is_using_input_method); assert.ok(search.is_using_input_method);
const keydown = searchbox_form.get_on_handler("keydown"); const keydown = $searchbox_form.get_on_handler("keydown");
let default_prevented = false; let default_prevented = false;
let ev = { let ev = {
type: "keydown", type: "keydown",
@@ -235,7 +236,7 @@ test("initialize", () => {
default_prevented = true; default_prevented = true;
}, },
}; };
search_query_box.is = () => false; $search_query_box.is = () => false;
assert.equal(keydown(ev), undefined); assert.equal(keydown(ev), undefined);
assert.ok(!default_prevented); assert.ok(!default_prevented);
@@ -244,22 +245,22 @@ test("initialize", () => {
assert.ok(!default_prevented); assert.ok(!default_prevented);
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
assert.equal(keydown(ev), undefined); assert.equal(keydown(ev), undefined);
assert.ok(default_prevented); assert.ok(default_prevented);
let operators; let operators;
let is_blurred; let is_blurred;
narrow_state.active = () => false; narrow_state.active = () => false;
search_query_box.off("blur"); $search_query_box.off("blur");
search_query_box.on("blur", () => { $search_query_box.on("blur", () => {
is_blurred = true; is_blurred = true;
}); });
const _setup = (search_box_val) => { const _setup = (search_box_val) => {
is_blurred = false; is_blurred = false;
search_button.prop("disabled", false); $search_button.prop("disabled", false);
search_query_box.val(search_box_val); $search_query_box.val(search_box_val);
Filter.parse = (search_string) => { Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val); assert.equal(search_string, search_box_val);
return operators; return operators;
@@ -284,41 +285,41 @@ test("initialize", () => {
type: "keyup", type: "keyup",
which: 15, which: 15,
}; };
search_query_box.is = () => false; $search_query_box.is = () => false;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => false; $search_query_box.is = () => false;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(is_blurred); assert.ok(is_blurred);
_setup("ver"); _setup("ver");
search.__Rewire__("is_using_input_method", true); search.__Rewire__("is_using_input_method", true);
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
// No change on Enter keyup event when using input tool // No change on Enter keyup event when using input tool
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
_setup("ver"); _setup("ver");
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(is_blurred); assert.ok(is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search_query_box.trigger("focus"); $search_query_box.trigger("focus");
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
}); });
test("initiate_search", () => { test("initiate_search", () => {
@@ -345,9 +346,9 @@ test("initiate_search", () => {
$("#search_query")[0] = "stub"; $("#search_query")[0] = "stub";
const searchbox = $("#searchbox"); const $searchbox = $("#searchbox");
let css_args; let css_args;
searchbox.css = (args) => { $searchbox.css = (args) => {
css_args = args; css_args = args;
}; };

View File

@@ -29,45 +29,45 @@ set_global("setTimeout", (func) => func());
const search = zrequire("search"); const search = zrequire("search");
run_test("update_button_visibility", () => { run_test("update_button_visibility", () => {
const search_query = $("#search_query"); const $search_query = $("#search_query");
const search_button = $(".search_button"); const $search_button = $(".search_button");
search_query.is = () => false; $search_query.is = () => false;
search_query.val(""); $search_query.val("");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(search_button.prop("disabled")); assert.ok($search_button.prop("disabled"));
search_query.is = () => true; $search_query.is = () => true;
search_query.val(""); $search_query.val("");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_query.is = () => false; $search_query.is = () => false;
search_query.val("Test search term"); $search_query.val("Test search term");
narrow_state.active = () => false; narrow_state.active = () => false;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_query.is = () => false; $search_query.is = () => false;
search_query.val(""); $search_query.val("");
narrow_state.active = () => true; narrow_state.active = () => true;
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search.update_button_visibility(); search.update_button_visibility();
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
}); });
run_test("initialize", () => { run_test("initialize", () => {
const search_query_box = $("#search_query"); const $search_query_box = $("#search_query");
const searchbox_form = $("#searchbox_form"); const $searchbox_form = $("#searchbox_form");
const search_button = $(".search_button"); const $search_button = $(".search_button");
search_suggestion.max_num_of_search_results = 999; search_suggestion.max_num_of_search_results = 999;
search_query_box.typeahead = (opts) => { $search_query_box.typeahead = (opts) => {
assert.equal(opts.fixed, true); assert.equal(opts.fixed, true);
assert.equal(opts.items, 999); assert.equal(opts.items, 999);
assert.equal(opts.naturalSearch, true); assert.equal(opts.naturalSearch, true);
@@ -115,13 +115,13 @@ run_test("initialize", () => {
{ {
let operators; let operators;
let is_blurred; let is_blurred;
search_query_box.on("blur", () => { $search_query_box.on("blur", () => {
is_blurred = true; is_blurred = true;
}); });
/* Test updater */ /* Test updater */
const _setup = (search_box_val) => { const _setup = (search_box_val) => {
is_blurred = false; is_blurred = false;
search_query_box.val(search_box_val); $search_query_box.val(search_box_val);
Filter.parse = (search_string) => { Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val); assert.equal(search_string, search_box_val);
return operators; return operators;
@@ -159,26 +159,26 @@ run_test("initialize", () => {
assert.equal(opts.updater("stream:Verona"), "stream:Verona"); assert.equal(opts.updater("stream:Verona"), "stream:Verona");
assert.ok(!is_blurred); assert.ok(!is_blurred);
search_query_box.off("blur"); $search_query_box.off("blur");
} }
}; };
search.initialize(); search.initialize();
search_button.prop("disabled", true); $search_button.prop("disabled", true);
search_query_box.trigger("focus"); $search_query_box.trigger("focus");
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
search_query_box.val("test string"); $search_query_box.val("test string");
narrow_state.search_string = () => "ver"; narrow_state.search_string = () => "ver";
search_query_box.trigger("blur"); $search_query_box.trigger("blur");
assert.equal(search_query_box.val(), "test string"); assert.equal($search_query_box.val(), "test string");
search.__Rewire__("is_using_input_method", false); search.__Rewire__("is_using_input_method", false);
searchbox_form.trigger("compositionend"); $searchbox_form.trigger("compositionend");
assert.ok(search.is_using_input_method); assert.ok(search.is_using_input_method);
const keydown = searchbox_form.get_on_handler("keydown"); const keydown = $searchbox_form.get_on_handler("keydown");
let default_prevented = false; let default_prevented = false;
let ev = { let ev = {
type: "keydown", type: "keydown",
@@ -187,7 +187,7 @@ run_test("initialize", () => {
default_prevented = true; default_prevented = true;
}, },
}; };
search_query_box.is = () => false; $search_query_box.is = () => false;
assert.equal(keydown(ev), undefined); assert.equal(keydown(ev), undefined);
assert.ok(!default_prevented); assert.ok(!default_prevented);
@@ -196,7 +196,7 @@ run_test("initialize", () => {
assert.ok(!default_prevented); assert.ok(!default_prevented);
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
assert.equal(keydown(ev), undefined); assert.equal(keydown(ev), undefined);
assert.ok(default_prevented); assert.ok(default_prevented);
@@ -206,15 +206,15 @@ run_test("initialize", () => {
let operators; let operators;
let is_blurred; let is_blurred;
narrow_state.active = () => false; narrow_state.active = () => false;
search_query_box.off("blur"); $search_query_box.off("blur");
search_query_box.on("blur", () => { $search_query_box.on("blur", () => {
is_blurred = true; is_blurred = true;
}); });
const _setup = (search_box_val) => { const _setup = (search_box_val) => {
is_blurred = false; is_blurred = false;
search_button.prop("disabled", false); $search_button.prop("disabled", false);
search_query_box.val(search_box_val); $search_query_box.val(search_box_val);
Filter.parse = (search_string) => { Filter.parse = (search_string) => {
assert.equal(search_string, search_box_val); assert.equal(search_string, search_box_val);
return operators; return operators;
@@ -235,37 +235,37 @@ run_test("initialize", () => {
_setup(""); _setup("");
ev.key = "a"; ev.key = "a";
search_query_box.is = () => false; $search_query_box.is = () => false;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => false; $search_query_box.is = () => false;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(is_blurred); assert.ok(is_blurred);
_setup("ver"); _setup("ver");
search.__Rewire__("is_using_input_method", true); search.__Rewire__("is_using_input_method", true);
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
// No change on Enter keyup event when using input tool // No change on Enter keyup event when using input tool
assert.ok(!is_blurred); assert.ok(!is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
_setup("ver"); _setup("ver");
ev.key = "Enter"; ev.key = "Enter";
search_query_box.is = () => true; $search_query_box.is = () => true;
searchbox_form.trigger(ev); $searchbox_form.trigger(ev);
assert.ok(is_blurred); assert.ok(is_blurred);
assert.ok(!search_button.prop("disabled")); assert.ok(!$search_button.prop("disabled"));
}); });
run_test("initiate_search", () => { run_test("initiate_search", () => {

View File

@@ -91,32 +91,32 @@ test("generate_botserverrc_content", () => {
}); });
function test_create_bot_type_input_box_toggle(f) { function test_create_bot_type_input_box_toggle(f) {
const create_payload_url = $("#create_payload_url"); const $create_payload_url = $("#create_payload_url");
const payload_url_inputbox = $("#payload_url_inputbox"); const $payload_url_inputbox = $("#payload_url_inputbox");
const config_inputbox = $("#config_inputbox"); const $config_inputbox = $("#config_inputbox");
const EMBEDDED_BOT_TYPE = "4"; const EMBEDDED_BOT_TYPE = "4";
const OUTGOING_WEBHOOK_BOT_TYPE = "3"; const OUTGOING_WEBHOOK_BOT_TYPE = "3";
const GENERIC_BOT_TYPE = "1"; const GENERIC_BOT_TYPE = "1";
$("#create_bot_type :selected").val(EMBEDDED_BOT_TYPE); $("#create_bot_type :selected").val(EMBEDDED_BOT_TYPE);
f(); f();
assert.ok(!create_payload_url.hasClass("required")); assert.ok(!$create_payload_url.hasClass("required"));
assert.ok(!payload_url_inputbox.visible()); assert.ok(!$payload_url_inputbox.visible());
assert.ok($("#select_service_name").hasClass("required")); assert.ok($("#select_service_name").hasClass("required"));
assert.ok($("#service_name_list").visible()); assert.ok($("#service_name_list").visible());
assert.ok(config_inputbox.visible()); assert.ok($config_inputbox.visible());
$("#create_bot_type :selected").val(OUTGOING_WEBHOOK_BOT_TYPE); $("#create_bot_type :selected").val(OUTGOING_WEBHOOK_BOT_TYPE);
f(); f();
assert.ok(create_payload_url.hasClass("required")); assert.ok($create_payload_url.hasClass("required"));
assert.ok(payload_url_inputbox.visible()); assert.ok($payload_url_inputbox.visible());
assert.ok(!config_inputbox.visible()); assert.ok(!$config_inputbox.visible());
$("#create_bot_type :selected").val(GENERIC_BOT_TYPE); $("#create_bot_type :selected").val(GENERIC_BOT_TYPE);
f(); f();
assert.ok(!create_payload_url.hasClass("required")); assert.ok(!$create_payload_url.hasClass("required"));
assert.ok(!payload_url_inputbox.visible()); assert.ok(!$payload_url_inputbox.visible());
assert.ok(!config_inputbox.visible()); assert.ok(!$config_inputbox.visible());
} }
test("test tab clicks", ({override}) => { test("test tab clicks", ({override}) => {
@@ -125,10 +125,10 @@ test("test tab clicks", ({override}) => {
$("#create_bot_form").validate = () => {}; $("#create_bot_form").validate = () => {};
$("#config_inputbox").children = () => { $("#config_inputbox").children = () => {
const mock_children = { const $mock_children = {
hide: () => {}, hide: () => {},
}; };
return mock_children; return $mock_children;
}; };
override(avatar, "build_bot_create_widget", () => {}); override(avatar, "build_bot_create_widget", () => {});
@@ -137,55 +137,55 @@ test("test tab clicks", ({override}) => {
test_create_bot_type_input_box_toggle(() => $("#create_bot_type").trigger("change")); test_create_bot_type_input_box_toggle(() => $("#create_bot_type").trigger("change"));
function click_on_tab(tab_elem) { function click_on_tab($tab_elem) {
tab_elem.trigger("click"); $tab_elem.trigger("click");
} }
const tabs = { const tabs = {
add: $("#bots_lists_navbar .add-a-new-bot-tab"), $add: $("#bots_lists_navbar .add-a-new-bot-tab"),
active: $("#bots_lists_navbar .active-bots-tab"), $active: $("#bots_lists_navbar .active-bots-tab"),
inactive: $("#bots_lists_navbar .inactive-bots-tab"), $inactive: $("#bots_lists_navbar .inactive-bots-tab"),
}; };
$("#bots_lists_navbar .active").removeClass = (cls) => { $("#bots_lists_navbar .active").removeClass = (cls) => {
assert.equal(cls, "active"); assert.equal(cls, "active");
for (const tab of Object.values(tabs)) { for (const $tab of Object.values(tabs)) {
tab.removeClass("active"); $tab.removeClass("active");
} }
}; };
const forms = { const forms = {
add: $("#add-a-new-bot-form"), $add: $("#add-a-new-bot-form"),
active: $("#active_bots_list"), $active: $("#active_bots_list"),
inactive: $("#inactive_bots_list"), $inactive: $("#inactive_bots_list"),
}; };
click_on_tab(tabs.add); click_on_tab(tabs.$add);
assert.ok(tabs.add.hasClass("active")); assert.ok(tabs.$add.hasClass("active"));
assert.ok(!tabs.active.hasClass("active")); assert.ok(!tabs.$active.hasClass("active"));
assert.ok(!tabs.inactive.hasClass("active")); assert.ok(!tabs.$inactive.hasClass("active"));
assert.ok(forms.add.visible()); assert.ok(forms.$add.visible());
assert.ok(!forms.active.visible()); assert.ok(!forms.$active.visible());
assert.ok(!forms.inactive.visible()); assert.ok(!forms.$inactive.visible());
click_on_tab(tabs.active); click_on_tab(tabs.$active);
assert.ok(!tabs.add.hasClass("active")); assert.ok(!tabs.$add.hasClass("active"));
assert.ok(tabs.active.hasClass("active")); assert.ok(tabs.$active.hasClass("active"));
assert.ok(!tabs.inactive.hasClass("active")); assert.ok(!tabs.$inactive.hasClass("active"));
assert.ok(!forms.add.visible()); assert.ok(!forms.$add.visible());
assert.ok(forms.active.visible()); assert.ok(forms.$active.visible());
assert.ok(!forms.inactive.visible()); assert.ok(!forms.$inactive.visible());
click_on_tab(tabs.inactive); click_on_tab(tabs.$inactive);
assert.ok(!tabs.add.hasClass("active")); assert.ok(!tabs.$add.hasClass("active"));
assert.ok(!tabs.active.hasClass("active")); assert.ok(!tabs.$active.hasClass("active"));
assert.ok(tabs.inactive.hasClass("active")); assert.ok(tabs.$inactive.hasClass("active"));
assert.ok(!forms.add.visible()); assert.ok(!forms.$add.visible());
assert.ok(!forms.active.visible()); assert.ok(!forms.$active.visible());
assert.ok(forms.inactive.visible()); assert.ok(forms.$inactive.visible());
}); });
test("can_create_new_bots", () => { test("can_create_new_bots", () => {

View File

@@ -51,15 +51,15 @@ run_test("settings", ({override_rewire}) => {
stopPropagation: noop, stopPropagation: noop,
}; };
const topic_fake_this = $.create("fake.settings-unmute-topic"); const $topic_fake_this = $.create("fake.settings-unmute-topic");
const topic_tr_html = $('tr[data-topic="js"]'); const $topic_tr_html = $('tr[data-topic="js"]');
topic_fake_this.closest = (opts) => { $topic_fake_this.closest = (opts) => {
assert.equal(opts, "tr"); assert.equal(opts, "tr");
return topic_tr_html; return $topic_tr_html;
}; };
let topic_data_called = 0; let topic_data_called = 0;
topic_tr_html.attr = (opts) => { $topic_tr_html.attr = (opts) => {
if (opts === "data-stream-id") { if (opts === "data-stream-id") {
topic_data_called += 1; topic_data_called += 1;
return frontend.stream_id; return frontend.stream_id;
@@ -77,7 +77,7 @@ run_test("settings", ({override_rewire}) => {
assert.equal(topic, "js"); assert.equal(topic, "js");
unmute_topic_called = true; unmute_topic_called = true;
}; };
topic_click_handler.call(topic_fake_this, event); topic_click_handler.call($topic_fake_this, event);
assert.ok(unmute_topic_called); assert.ok(unmute_topic_called);
assert.equal(topic_data_called, 2); assert.equal(topic_data_called, 2);
}); });

View File

@@ -42,15 +42,15 @@ run_test("settings", ({override_rewire}) => {
stopPropagation: noop, stopPropagation: noop,
}; };
const unmute_button = $.create("settings-unmute-user"); const $unmute_button = $.create("settings-unmute-user");
const fake_row = $('tr[data-user-id="5"]'); const $fake_row = $('tr[data-user-id="5"]');
unmute_button.closest = (opts) => { $unmute_button.closest = (opts) => {
assert.equal(opts, "tr"); assert.equal(opts, "tr");
return fake_row; return $fake_row;
}; };
let row_attribute_fetched = false; let row_attribute_fetched = false;
fake_row.attr = (opts) => { $fake_row.attr = (opts) => {
if (opts === "data-user-id") { if (opts === "data-user-id") {
row_attribute_fetched += 1; row_attribute_fetched += 1;
return "5"; return "5";
@@ -64,7 +64,7 @@ run_test("settings", ({override_rewire}) => {
unmute_user_called = true; unmute_user_called = true;
}; };
unmute_click_handler.call(unmute_button, event); unmute_click_handler.call($unmute_button, event);
assert.ok(unmute_user_called); assert.ok(unmute_user_called);
assert.ok(row_attribute_fetched); assert.ok(row_attribute_fetched);
}); });

View File

@@ -31,12 +31,12 @@ mock_esm("../../static/js/loading", {
destroy_indicator: noop, destroy_indicator: noop,
}); });
mock_esm("../../static/js/ui_report", { mock_esm("../../static/js/ui_report", {
success(msg, elem) { success(msg, $elem) {
elem.val(msg); $elem.val(msg);
}, },
error(msg, xhr, elem) { error(msg, xhr, $elem) {
elem.val(msg); $elem.val(msg);
}, },
}); });
@@ -74,9 +74,9 @@ test("unloaded", () => {
}); });
function simulate_realm_domains_table() { function simulate_realm_domains_table() {
const tr_stub = $.create("realm-tr-stub"); const $tr_stub = $.create("realm-tr-stub");
$("#realm_domains_table tbody").set_find_results("tr", tr_stub); $("#realm_domains_table tbody").set_find_results("tr", $tr_stub);
tr_stub.remove = () => {}; $tr_stub.remove = () => {};
let appended; let appended;
$("#realm_domains_table tbody").append = (html) => { $("#realm_domains_table tbody").append = (html) => {
@@ -90,7 +90,7 @@ function simulate_realm_domains_table() {
} }
function test_realms_domain_modal(override, add_realm_domain) { function test_realms_domain_modal(override, add_realm_domain) {
const info = $(".realm_domains_info"); const $info = $(".realm_domains_info");
$("#add-realm-domain-widget").set_find_results( $("#add-realm-domain-widget").set_find_results(
".new-realm-domain", ".new-realm-domain",
@@ -117,46 +117,46 @@ function test_realms_domain_modal(override, add_realm_domain) {
assert.ok(posted); assert.ok(posted);
success_callback(); success_callback();
assert.equal(info.val(), "translated HTML: Added successfully!"); assert.equal($info.val(), "translated HTML: Added successfully!");
error_callback({}); error_callback({});
assert.equal(info.val(), "translated HTML: Failed"); assert.equal($info.val(), "translated HTML: Failed");
} }
function createSaveButtons(subsection) { function createSaveButtons(subsection) {
const stub_save_button_header = $(`#org-${CSS.escape(subsection)}`); const $stub_save_button_header = $(`#org-${CSS.escape(subsection)}`);
const save_button_controls = $(".save-button-controls"); const $save_button_controls = $(".save-button-controls");
const stub_save_button = $(`#org-submit-${CSS.escape(subsection)}`); const $stub_save_button = $(`#org-submit-${CSS.escape(subsection)}`);
const stub_discard_button = $(`#org-discard-${CSS.escape(subsection)}`); const $stub_discard_button = $(`#org-discard-${CSS.escape(subsection)}`);
const stub_save_button_text = $(".save-discard-widget-button-text"); const $stub_save_button_text = $(".save-discard-widget-button-text");
stub_save_button_header.set_find_results( $stub_save_button_header.set_find_results(
".subsection-failed-status p", ".subsection-failed-status p",
$("<failed status element>"), $("<failed status element>"),
); );
stub_save_button.closest = () => stub_save_button_header; $stub_save_button.closest = () => $stub_save_button_header;
save_button_controls.set_find_results(".save-button", stub_save_button); $save_button_controls.set_find_results(".save-button", $stub_save_button);
stub_save_button.set_find_results(".save-discard-widget-button-text", stub_save_button_text); $stub_save_button.set_find_results(".save-discard-widget-button-text", $stub_save_button_text);
stub_save_button_header.set_find_results(".save-button-controls", save_button_controls); $stub_save_button_header.set_find_results(".save-button-controls", $save_button_controls);
stub_save_button_header.set_find_results( $stub_save_button_header.set_find_results(
".subsection-changes-discard button", ".subsection-changes-discard button",
$(`#org-discard-${CSS.escape(subsection)}`), $(`#org-discard-${CSS.escape(subsection)}`),
); );
save_button_controls.set_find_results(".discard-button", stub_discard_button); $save_button_controls.set_find_results(".discard-button", $stub_discard_button);
const props = {}; const props = {};
props.hidden = false; props.hidden = false;
save_button_controls.fadeIn = () => { $save_button_controls.fadeIn = () => {
props.hidden = false; props.hidden = false;
}; };
save_button_controls.fadeOut = () => { $save_button_controls.fadeOut = () => {
props.hidden = true; props.hidden = true;
}; };
return { return {
props, props,
save_button: stub_save_button, $save_button: $stub_save_button,
discard_button: stub_discard_button, $discard_button: $stub_discard_button,
save_button_header: stub_save_button_header, $save_button_header: $stub_save_button_header,
save_button_controls, $save_button_controls,
save_button_text: stub_save_button_text, $save_button_text: $stub_save_button_text,
}; };
} }
@@ -193,55 +193,55 @@ function test_submit_settings_form(override, submit_form) {
let subsection = "other-permissions"; let subsection = "other-permissions";
ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`; ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`;
let stubs = createSaveButtons(subsection); let stubs = createSaveButtons(subsection);
let save_button = stubs.save_button; let $save_button = stubs.$save_button;
save_button.attr("id", `org-submit-${subsection}`); $save_button.attr("id", `org-submit-${subsection}`);
save_button.replace = () => `${subsection}`; $save_button.replace = () => `${subsection}`;
$("#id_realm_waiting_period_threshold").val(10); $("#id_realm_waiting_period_threshold").val(10);
const invite_to_stream_policy_elem = $("#id_realm_invite_to_stream_policy"); const $invite_to_stream_policy_elem = $("#id_realm_invite_to_stream_policy");
invite_to_stream_policy_elem.val("1"); $invite_to_stream_policy_elem.val("1");
invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy"); $invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy");
invite_to_stream_policy_elem.data = () => "number"; $invite_to_stream_policy_elem.data = () => "number";
const create_public_stream_policy_elem = $("#id_realm_create_public_stream_policy"); const $create_public_stream_policy_elem = $("#id_realm_create_public_stream_policy");
create_public_stream_policy_elem.val("2"); $create_public_stream_policy_elem.val("2");
create_public_stream_policy_elem.attr("id", "id_realm_create_public_stream_policy"); $create_public_stream_policy_elem.attr("id", "id_realm_create_public_stream_policy");
create_public_stream_policy_elem.data = () => "number"; $create_public_stream_policy_elem.data = () => "number";
const create_private_stream_policy_elem = $("#id_realm_create_private_stream_policy"); const $create_private_stream_policy_elem = $("#id_realm_create_private_stream_policy");
create_private_stream_policy_elem.val("2"); $create_private_stream_policy_elem.val("2");
create_private_stream_policy_elem.attr("id", "id_realm_create_private_stream_policy"); $create_private_stream_policy_elem.attr("id", "id_realm_create_private_stream_policy");
create_private_stream_policy_elem.data = () => "number"; $create_private_stream_policy_elem.data = () => "number";
const add_custom_emoji_policy_elem = $("#id_realm_add_custom_emoji_policy"); const $add_custom_emoji_policy_elem = $("#id_realm_add_custom_emoji_policy");
add_custom_emoji_policy_elem.val("1"); $add_custom_emoji_policy_elem.val("1");
add_custom_emoji_policy_elem.attr("id", "id_realm_add_custom_emoji_policy"); $add_custom_emoji_policy_elem.attr("id", "id_realm_add_custom_emoji_policy");
add_custom_emoji_policy_elem.data = () => "number"; $add_custom_emoji_policy_elem.data = () => "number";
const bot_creation_policy_elem = $("#id_realm_bot_creation_policy"); const $bot_creation_policy_elem = $("#id_realm_bot_creation_policy");
bot_creation_policy_elem.val("1"); $bot_creation_policy_elem.val("1");
bot_creation_policy_elem.attr("id", "id_realm_bot_creation_policy"); $bot_creation_policy_elem.attr("id", "id_realm_bot_creation_policy");
bot_creation_policy_elem.data = () => "number"; $bot_creation_policy_elem.data = () => "number";
const email_address_visibility_elem = $("#id_realm_email_address_visibility"); const $email_address_visibility_elem = $("#id_realm_email_address_visibility");
email_address_visibility_elem.val("1"); $email_address_visibility_elem.val("1");
email_address_visibility_elem.attr("id", "id_realm_email_address_visibility"); $email_address_visibility_elem.attr("id", "id_realm_email_address_visibility");
email_address_visibility_elem.data = () => "number"; $email_address_visibility_elem.data = () => "number";
const invite_to_realm_policy_elem = $("#id_realm_invite_to_realm_policy"); const $invite_to_realm_policy_elem = $("#id_realm_invite_to_realm_policy");
invite_to_realm_policy_elem.val("2"); $invite_to_realm_policy_elem.val("2");
invite_to_realm_policy_elem.attr("id", "id_realm_invite_to_realm_policy"); $invite_to_realm_policy_elem.attr("id", "id_realm_invite_to_realm_policy");
invite_to_realm_policy_elem.data = () => "number"; $invite_to_realm_policy_elem.data = () => "number";
let subsection_elem = $(`#org-${CSS.escape(subsection)}`); let $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
subsection_elem.closest = () => subsection_elem; $subsection_elem.closest = () => $subsection_elem;
subsection_elem.set_find_results(".prop-element", [ $subsection_elem.set_find_results(".prop-element", [
bot_creation_policy_elem, $bot_creation_policy_elem,
email_address_visibility_elem, $email_address_visibility_elem,
add_custom_emoji_policy_elem, $add_custom_emoji_policy_elem,
create_public_stream_policy_elem, $create_public_stream_policy_elem,
create_private_stream_policy_elem, $create_private_stream_policy_elem,
invite_to_stream_policy_elem, $invite_to_stream_policy_elem,
]); ]);
patched = false; patched = false;
@@ -261,17 +261,17 @@ function test_submit_settings_form(override, submit_form) {
subsection = "user-defaults"; subsection = "user-defaults";
ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`; ev.currentTarget = `#org-submit-${CSS.escape(subsection)}`;
stubs = createSaveButtons(subsection); stubs = createSaveButtons(subsection);
save_button = stubs.save_button; $save_button = stubs.$save_button;
save_button.attr("id", `org-submit-${subsection}`); $save_button.attr("id", `org-submit-${subsection}`);
const realm_default_language_elem = $("#id_realm_default_language"); const $realm_default_language_elem = $("#id_realm_default_language");
realm_default_language_elem.val("en"); $realm_default_language_elem.val("en");
realm_default_language_elem.attr("id", "id_realm_default_language"); $realm_default_language_elem.attr("id", "id_realm_default_language");
realm_default_language_elem.data = () => "string"; $realm_default_language_elem.data = () => "string";
subsection_elem = $(`#org-${CSS.escape(subsection)}`); $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
subsection_elem.closest = () => subsection_elem; $subsection_elem.closest = () => $subsection_elem;
subsection_elem.set_find_results(".prop-element", [realm_default_language_elem]); $subsection_elem.set_find_results(".prop-element", [$realm_default_language_elem]);
submit_form(ev); submit_form(ev);
assert.ok(patched); assert.ok(patched);
@@ -284,50 +284,50 @@ function test_submit_settings_form(override, submit_form) {
// Testing only once for since callback is same for all cases // Testing only once for since callback is same for all cases
success_callback(); success_callback();
assert.equal(stubs.props.hidden, true); assert.equal(stubs.props.hidden, true);
assert.equal(save_button.attr("data-status"), "saved"); assert.equal($save_button.attr("data-status"), "saved");
assert.equal(stubs.save_button_text.text(), "translated: Saved"); assert.equal(stubs.$save_button_text.text(), "translated: Saved");
} }
function test_change_save_button_state() { function test_change_save_button_state() {
const {save_button_controls, save_button_text, save_button, discard_button, props} = const {$save_button_controls, $save_button_text, $save_button, $discard_button, props} =
createSaveButtons("msg-editing"); createSaveButtons("msg-editing");
save_button.attr("id", "org-submit-msg-editing"); $save_button.attr("id", "org-submit-msg-editing");
{ {
settings_org.change_save_button_state(save_button_controls, "unsaved"); settings_org.change_save_button_state($save_button_controls, "unsaved");
assert.equal(save_button_text.text(), "translated: Save changes"); assert.equal($save_button_text.text(), "translated: Save changes");
assert.equal(props.hidden, false); assert.equal(props.hidden, false);
assert.equal(save_button.attr("data-status"), "unsaved"); assert.equal($save_button.attr("data-status"), "unsaved");
assert.equal(discard_button.visible(), true); assert.equal($discard_button.visible(), true);
} }
{ {
settings_org.change_save_button_state(save_button_controls, "saved"); settings_org.change_save_button_state($save_button_controls, "saved");
assert.equal(save_button_text.text(), "translated: Save changes"); assert.equal($save_button_text.text(), "translated: Save changes");
assert.equal(props.hidden, true); assert.equal(props.hidden, true);
assert.equal(save_button.attr("data-status"), ""); assert.equal($save_button.attr("data-status"), "");
} }
{ {
settings_org.change_save_button_state(save_button_controls, "saving"); settings_org.change_save_button_state($save_button_controls, "saving");
assert.equal(save_button_text.text(), "translated: Saving"); assert.equal($save_button_text.text(), "translated: Saving");
assert.equal(save_button.attr("data-status"), "saving"); assert.equal($save_button.attr("data-status"), "saving");
assert.equal(save_button.hasClass("saving"), true); assert.equal($save_button.hasClass("saving"), true);
assert.equal(discard_button.visible(), false); assert.equal($discard_button.visible(), false);
} }
{ {
settings_org.change_save_button_state(save_button_controls, "discarded"); settings_org.change_save_button_state($save_button_controls, "discarded");
assert.equal(props.hidden, true); assert.equal(props.hidden, true);
} }
{ {
settings_org.change_save_button_state(save_button_controls, "succeeded"); settings_org.change_save_button_state($save_button_controls, "succeeded");
assert.equal(props.hidden, true); assert.equal(props.hidden, true);
assert.equal(save_button.attr("data-status"), "saved"); assert.equal($save_button.attr("data-status"), "saved");
assert.equal(save_button_text.text(), "translated: Saved"); assert.equal($save_button_text.text(), "translated: Saved");
} }
{ {
settings_org.change_save_button_state(save_button_controls, "failed"); settings_org.change_save_button_state($save_button_controls, "failed");
assert.equal(props.hidden, false); assert.equal(props.hidden, false);
assert.equal(save_button.attr("data-status"), "failed"); assert.equal($save_button.attr("data-status"), "failed");
assert.equal(save_button_text.text(), "translated: Save changes"); assert.equal($save_button_text.text(), "translated: Save changes");
} }
} }
@@ -358,8 +358,8 @@ function test_change_allow_subdomains(change_allow_subdomains) {
stopPropagation: noop, stopPropagation: noop,
}; };
const info = $(".realm_domains_info"); const $info = $(".realm_domains_info");
info.fadeOut = noop; $info.fadeOut = noop;
const domain = "example.com"; const domain = "example.com";
let allow = true; let allow = true;
@@ -372,33 +372,33 @@ function test_change_allow_subdomains(change_allow_subdomains) {
error_callback = req.error; error_callback = req.error;
}; };
const domain_obj = $.create("domain object"); const $domain_obj = $.create("domain object");
domain_obj.text(domain); $domain_obj.text(domain);
const elem_obj = $.create("<elem html>"); const $elem_obj = $.create("<elem html>");
const parents_obj = $.create("parents object"); const $parents_obj = $.create("parents object");
elem_obj.set_parents_result("tr", parents_obj); $elem_obj.set_parents_result("tr", $parents_obj);
parents_obj.set_find_results(".domain", domain_obj); $parents_obj.set_find_results(".domain", $domain_obj);
elem_obj.prop("checked", allow); $elem_obj.prop("checked", allow);
change_allow_subdomains.call(elem_obj, ev); change_allow_subdomains.call($elem_obj, ev);
success_callback(); success_callback();
assert.equal( assert.equal(
info.val(), $info.val(),
"translated HTML: Update successful: Subdomains allowed for example.com", "translated HTML: Update successful: Subdomains allowed for example.com",
); );
error_callback({}); error_callback({});
assert.equal(info.val(), "translated HTML: Failed"); assert.equal($info.val(), "translated HTML: Failed");
allow = false; allow = false;
elem_obj.prop("checked", allow); $elem_obj.prop("checked", allow);
change_allow_subdomains.call(elem_obj, ev); change_allow_subdomains.call($elem_obj, ev);
success_callback(); success_callback();
assert.equal( assert.equal(
info.val(), $info.val(),
"translated HTML: Update successful: Subdomains no longer allowed for example.com", "translated HTML: Update successful: Subdomains no longer allowed for example.com",
); );
} }
@@ -431,9 +431,9 @@ function test_sync_realm_settings() {
{ {
/* Test invalid settings property sync */ /* Test invalid settings property sync */
const property_elem = $("#id_realm_invalid_settings_property"); const $property_elem = $("#id_realm_invalid_settings_property");
property_elem.attr("id", "id_realm_invalid_settings_property"); $property_elem.attr("id", "id_realm_invalid_settings_property");
property_elem.length = 1; $property_elem.length = 1;
blueslip.expect( blueslip.expect(
"error", "error",
@@ -443,9 +443,9 @@ function test_sync_realm_settings() {
} }
function test_common_policy(property_name) { function test_common_policy(property_name) {
const property_elem = $(`#id_realm_${CSS.escape(property_name)}`); const $property_elem = $(`#id_realm_${CSS.escape(property_name)}`);
property_elem.length = 1; $property_elem.length = 1;
property_elem.attr("id", `id_realm_${CSS.escape(property_name)}`); $property_elem.attr("id", `id_realm_${CSS.escape(property_name)}`);
/* Each policy is initialized to 'by_members' and then all the values are tested /* Each policy is initialized to 'by_members' and then all the values are tested
in the following order - by_admins_only, by_moderators_only, by_full_members, in the following order - by_admins_only, by_moderators_only, by_full_members,
@@ -453,14 +453,14 @@ function test_sync_realm_settings() {
page_params[`realm_${property_name}`] = page_params[`realm_${property_name}`] =
settings_config.common_policy_values.by_members.code; settings_config.common_policy_values.by_members.code;
property_elem.val(settings_config.common_policy_values.by_members.code); $property_elem.val(settings_config.common_policy_values.by_members.code);
for (const policy_value of Array.from( for (const policy_value of Array.from(
Object.values(settings_config.common_policy_values), Object.values(settings_config.common_policy_values),
)) { )) {
page_params[`realm_${property_name}`] = policy_value.code; page_params[`realm_${property_name}`] = policy_value.code;
settings_org.sync_realm_settings(property_name); settings_org.sync_realm_settings(property_name);
assert.equal(property_elem.val(), policy_value.code); assert.equal($property_elem.val(), policy_value.code);
} }
} }
@@ -471,9 +471,9 @@ function test_sync_realm_settings() {
{ {
/* Test message content edit limit minutes sync */ /* Test message content edit limit minutes sync */
const property_elem = $("#id_realm_message_content_edit_limit_minutes"); const $property_elem = $("#id_realm_message_content_edit_limit_minutes");
property_elem.length = 1; $property_elem.length = 1;
property_elem.attr("id", "id_realm_message_content_edit_limit_minutes"); $property_elem.attr("id", "id_realm_message_content_edit_limit_minutes");
page_params.realm_create_public_stream_policy = 1; page_params.realm_create_public_stream_policy = 1;
page_params.realm_message_content_edit_limit_seconds = 120; page_params.realm_message_content_edit_limit_seconds = 120;
@@ -484,9 +484,9 @@ function test_sync_realm_settings() {
{ {
/* Test message content edit limit dropdown value sync */ /* Test message content edit limit dropdown value sync */
const property_elem = $("#id_realm_msg_edit_limit_setting"); const $property_elem = $("#id_realm_msg_edit_limit_setting");
property_elem.length = 1; $property_elem.length = 1;
property_elem.attr("id", "id_realm_msg_edit_limit_setting"); $property_elem.attr("id", "id_realm_msg_edit_limit_setting");
page_params.realm_allow_message_editing = false; page_params.realm_allow_message_editing = false;
page_params.realm_message_content_edit_limit_seconds = 120; page_params.realm_message_content_edit_limit_seconds = 120;
@@ -506,9 +506,9 @@ function test_sync_realm_settings() {
{ {
/* Test message content edit limit minutes sync */ /* Test message content edit limit minutes sync */
const property_elem = $("#id_realm_message_content_edit_limit_minutes"); const $property_elem = $("#id_realm_message_content_edit_limit_minutes");
property_elem.length = 1; $property_elem.length = 1;
property_elem.attr("id", "id_realm_message_content_edit_limit_minutes"); $property_elem.attr("id", "id_realm_message_content_edit_limit_minutes");
page_params.realm_create_public_stream_policy = 1; page_params.realm_create_public_stream_policy = 1;
page_params.realm_message_content_edit_limit_seconds = 120; page_params.realm_message_content_edit_limit_seconds = 120;
@@ -519,9 +519,9 @@ function test_sync_realm_settings() {
{ {
/* Test organization joining restrictions settings sync */ /* Test organization joining restrictions settings sync */
const property_elem = $("#id_realm_org_join_restrictions"); const $property_elem = $("#id_realm_org_join_restrictions");
property_elem.length = 1; $property_elem.length = 1;
property_elem.attr("id", "id_realm_org_join_restrictions"); $property_elem.attr("id", "id_realm_org_join_restrictions");
page_params.realm_emails_restricted_to_domains = true; page_params.realm_emails_restricted_to_domains = true;
page_params.realm_disallow_disposable_email_addresses = false; page_params.realm_disallow_disposable_email_addresses = false;
@@ -541,10 +541,10 @@ function test_sync_realm_settings() {
} }
function test_parse_time_limit() { function test_parse_time_limit() {
const elem = $("#id_realm_message_content_edit_limit_minutes"); const $elem = $("#id_realm_message_content_edit_limit_minutes");
const test_function = (value, expected_value = value) => { const test_function = (value, expected_value = value) => {
elem.val(value); $elem.val(value);
page_params.realm_message_content_edit_limit_seconds = settings_org.parse_time_limit(elem); page_params.realm_message_content_edit_limit_seconds = settings_org.parse_time_limit($elem);
assert.equal( assert.equal(
settings_org.get_realm_time_limits_in_minutes( settings_org.get_realm_time_limits_in_minutes(
"realm_message_content_edit_limit_seconds", "realm_message_content_edit_limit_seconds",
@@ -587,40 +587,40 @@ function test_discard_changes_button(discard_changes) {
settings_config.common_message_policy_values.by_everyone.code; settings_config.common_message_policy_values.by_everyone.code;
page_params.realm_message_content_delete_limit_seconds = 120; page_params.realm_message_content_delete_limit_seconds = 120;
const allow_edit_history = $("#id_realm_allow_edit_history").prop("checked", false); const $allow_edit_history = $("#id_realm_allow_edit_history").prop("checked", false);
const edit_topic_policy = $("#id_realm_edit_topic_policy").val( const $edit_topic_policy = $("#id_realm_edit_topic_policy").val(
settings_config.common_message_policy_values.by_admins_only.code, settings_config.common_message_policy_values.by_admins_only.code,
); );
const msg_edit_limit_setting = $("#id_realm_msg_edit_limit_setting").val("custom_limit"); const $msg_edit_limit_setting = $("#id_realm_msg_edit_limit_setting").val("custom_limit");
const message_content_edit_limit_minutes = $( const $message_content_edit_limit_minutes = $(
"#id_realm_message_content_edit_limit_minutes", "#id_realm_message_content_edit_limit_minutes",
).val(130); ).val(130);
const msg_delete_limit_setting = $("#id_realm_msg_delete_limit_setting").val("custom_limit"); const $msg_delete_limit_setting = $("#id_realm_msg_delete_limit_setting").val("custom_limit");
const message_content_delete_limit_minutes = $( const $message_content_delete_limit_minutes = $(
"#id_realm_message_content_delete_limit_minutes", "#id_realm_message_content_delete_limit_minutes",
).val(130); ).val(130);
allow_edit_history.attr("id", "id_realm_allow_edit_history"); $allow_edit_history.attr("id", "id_realm_allow_edit_history");
msg_edit_limit_setting.attr("id", "id_realm_msg_edit_limit_setting"); $msg_edit_limit_setting.attr("id", "id_realm_msg_edit_limit_setting");
msg_delete_limit_setting.attr("id", "id_realm_msg_delete_limit_setting"); $msg_delete_limit_setting.attr("id", "id_realm_msg_delete_limit_setting");
edit_topic_policy.attr("id", "id_realm_edit_topic_policy"); $edit_topic_policy.attr("id", "id_realm_edit_topic_policy");
message_content_edit_limit_minutes.attr("id", "id_realm_message_content_edit_limit_minutes"); $message_content_edit_limit_minutes.attr("id", "id_realm_message_content_edit_limit_minutes");
message_content_delete_limit_minutes.attr( $message_content_delete_limit_minutes.attr(
"id", "id",
"id_realm_message_content_delete_limit_minutes", "id_realm_message_content_delete_limit_minutes",
); );
const discard_button_parent = $(".org-subsection-parent"); const $discard_button_parent = $(".org-subsection-parent");
discard_button_parent.find = () => [ $discard_button_parent.find = () => [
allow_edit_history, $allow_edit_history,
msg_edit_limit_setting, $msg_edit_limit_setting,
msg_delete_limit_setting, $msg_delete_limit_setting,
edit_topic_policy, $edit_topic_policy,
message_content_edit_limit_minutes, $message_content_edit_limit_minutes,
message_content_delete_limit_minutes, $message_content_delete_limit_minutes,
]; ];
$("#org-discard-msg-editing").closest = () => discard_button_parent; $("#org-discard-msg-editing").closest = () => $discard_button_parent;
const stubbed_function = settings_org.change_save_button_state; const stubbed_function = settings_org.change_save_button_state;
settings_org.__Rewire__("change_save_button_state", (save_button_controls, state) => { settings_org.__Rewire__("change_save_button_state", (save_button_controls, state) => {
@@ -629,15 +629,15 @@ function test_discard_changes_button(discard_changes) {
discard_changes(ev); discard_changes(ev);
assert.equal(allow_edit_history.prop("checked"), true); assert.equal($allow_edit_history.prop("checked"), true);
assert.equal( assert.equal(
edit_topic_policy.val(), $edit_topic_policy.val(),
settings_config.common_message_policy_values.by_everyone.code, settings_config.common_message_policy_values.by_everyone.code,
); );
assert.equal(msg_edit_limit_setting.val(), "upto_one_hour"); assert.equal($msg_edit_limit_setting.val(), "upto_one_hour");
assert.equal(message_content_edit_limit_minutes.val(), "60"); assert.equal($message_content_edit_limit_minutes.val(), "60");
assert.equal(msg_delete_limit_setting.val(), "upto_two_min"); assert.equal($msg_delete_limit_setting.val(), "upto_two_min");
assert.equal(message_content_delete_limit_minutes.val(), "2"); assert.equal($message_content_delete_limit_minutes.val(), "2");
settings_org.__Rewire__("change_save_button_state", stubbed_function); settings_org.__Rewire__("change_save_button_state", stubbed_function);
} }
@@ -683,8 +683,8 @@ test("set_up", ({override, override_rewire, mock_template}) => {
$("#enable_digest_emails_label").set_parent($.create("<stub digest setting checkbox>")); $("#enable_digest_emails_label").set_parent($.create("<stub digest setting checkbox>"));
$("#id_realm_digest_weekday").set_parent($.create("<stub digest weekday setting dropdown>")); $("#id_realm_digest_weekday").set_parent($.create("<stub digest weekday setting dropdown>"));
$("#allowed_domains_label").set_parent($.create("<stub-allowed-domain-label-parent>")); $("#allowed_domains_label").set_parent($.create("<stub-allowed-domain-label-parent>"));
const waiting_period_parent_elem = $.create("waiting-period-parent-stub"); const $waiting_period_parent_elem = $.create("waiting-period-parent-stub");
$("#id_realm_waiting_period_threshold").set_parent(waiting_period_parent_elem); $("#id_realm_waiting_period_threshold").set_parent($waiting_period_parent_elem);
$("#id_realm_create_web_public_stream_policy").set_parent( $("#id_realm_create_web_public_stream_policy").set_parent(
$.create("<stub-create-web-public-stream-policy-parent>"), $.create("<stub-create-web-public-stream-policy-parent>"),
); );
@@ -829,8 +829,8 @@ test("test get_sorted_options_list", () => {
test("misc", ({override_rewire}) => { test("misc", ({override_rewire}) => {
page_params.is_admin = false; page_params.is_admin = false;
const stub_notification_disable_parent = $.create("<stub notification_disable parent"); const $stub_notification_disable_parent = $.create("<stub notification_disable parent");
stub_notification_disable_parent.set_find_results( $stub_notification_disable_parent.set_find_results(
".dropdown_list_reset_button", ".dropdown_list_reset_button",
$.create("<disable link>"), $.create("<disable link>"),
); );
@@ -904,14 +904,14 @@ test("misc", ({override_rewire}) => {
"realm_signup_notifications_stream_id", "realm_signup_notifications_stream_id",
"realm_default_code_block_language", "realm_default_code_block_language",
]; ];
const dropdown_list_parent = $.create("<list parent>"); const $dropdown_list_parent = $.create("<list parent>");
dropdown_list_parent.set_find_results( $dropdown_list_parent.set_find_results(
".dropdown_list_reset_button", ".dropdown_list_reset_button",
$.create("<disable button>"), $.create("<disable button>"),
); );
for (const name of widget_settings) { for (const name of widget_settings) {
const elem = $.create(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`); const $elem = $.create(`#${CSS.escape(name)}_widget #${CSS.escape(name)}_name`);
elem.closest = () => dropdown_list_parent; $elem.closest = () => $dropdown_list_parent;
} }
// We do not define any settings we need in page_params yet, but we don't need to for this test. // We do not define any settings we need in page_params yet, but we don't need to for this test.
@@ -923,32 +923,32 @@ test("misc", ({override_rewire}) => {
settings_org.init_dropdown_widgets(); settings_org.init_dropdown_widgets();
let setting_name = "realm_notifications_stream_id"; let setting_name = "realm_notifications_stream_id";
let elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`); let $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
elem.closest = () => stub_notification_disable_parent; $elem.closest = () => $stub_notification_disable_parent;
sub_store.__Rewire__("get", (stream_id) => { sub_store.__Rewire__("get", (stream_id) => {
assert.equal(stream_id, 42); assert.equal(stream_id, 42);
return {name: "some_stream"}; return {name: "some_stream"};
}); });
settings_org.notifications_stream_widget.render(42); settings_org.notifications_stream_widget.render(42);
assert.equal(elem.text(), "#some_stream"); assert.equal($elem.text(), "#some_stream");
assert.ok(!elem.hasClass("text-warning")); assert.ok(!$elem.hasClass("text-warning"));
settings_org.notifications_stream_widget.render(undefined); settings_org.notifications_stream_widget.render(undefined);
assert.equal(elem.text(), "translated: Disabled"); assert.equal($elem.text(), "translated: Disabled");
assert.ok(elem.hasClass("text-warning")); assert.ok($elem.hasClass("text-warning"));
setting_name = "realm_signup_notifications_stream_id"; setting_name = "realm_signup_notifications_stream_id";
elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`); $elem = $(`#${CSS.escape(setting_name)}_widget #${CSS.escape(setting_name)}_name`);
elem.closest = () => stub_notification_disable_parent; $elem.closest = () => $stub_notification_disable_parent;
sub_store.__Rewire__("get", (stream_id) => { sub_store.__Rewire__("get", (stream_id) => {
assert.equal(stream_id, 75); assert.equal(stream_id, 75);
return {name: "some_stream"}; return {name: "some_stream"};
}); });
settings_org.signup_notifications_stream_widget.render(75); settings_org.signup_notifications_stream_widget.render(75);
assert.equal(elem.text(), "#some_stream"); assert.equal($elem.text(), "#some_stream");
assert.ok(!elem.hasClass("text-warning")); assert.ok(!$elem.hasClass("text-warning"));
settings_org.signup_notifications_stream_widget.render(undefined); settings_org.signup_notifications_stream_widget.render(undefined);
assert.equal(elem.text(), "translated: Disabled"); assert.equal($elem.text(), "translated: Disabled");
assert.ok(elem.hasClass("text-warning")); assert.ok($elem.hasClass("text-warning"));
}); });

View File

@@ -43,19 +43,19 @@ function test_populate(opts, template_data) {
const fields_data = opts.fields_data; const fields_data = opts.fields_data;
page_params.is_admin = opts.is_admin; page_params.is_admin = opts.is_admin;
const table = $("#admin_profile_fields_table"); const $table = $("#admin_profile_fields_table");
const rows = $.create("rows"); const $rows = $.create("rows");
const form = $.create("forms"); const $form = $.create("forms");
table.set_find_results("tr.profile-field-row", rows); $table.set_find_results("tr.profile-field-row", $rows);
table.set_find_results("tr.profile-field-form", form); $table.set_find_results("tr.profile-field-form", $form);
table[0] = "stub"; $table[0] = "stub";
rows.remove = () => {}; $rows.remove = () => {};
form.remove = () => {}; $form.remove = () => {};
let num_appends = 0; let num_appends = 0;
table.append = () => { $table.append = () => {
num_appends += 1; num_appends += 1;
}; };

View File

@@ -34,9 +34,9 @@ const settings_data = zrequire("settings_data");
const settings_user_groups = zrequire("settings_user_groups"); const settings_user_groups = zrequire("settings_user_groups");
const user_pill = zrequire("user_pill"); const user_pill = zrequire("user_pill");
function reset_test_setup(pill_container_stub) { function reset_test_setup($pill_container_stub) {
function input_pill_stub(opts) { function input_pill_stub(opts) {
assert.equal(opts.container, pill_container_stub); assert.equal(opts.$container, $pill_container_stub);
create_item_handler = opts.create_item_from_text; create_item_handler = opts.create_item_from_text;
assert.ok(create_item_handler); assert.ok(create_item_handler);
return pills; return pills;
@@ -119,18 +119,18 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
people.get_visible_email = () => bob.email; people.get_visible_email = () => bob.email;
let templates_render_called = false; let templates_render_called = false;
const fake_rendered_temp = $.create("fake_admin_user_group_list_template_rendered"); const $fake_rendered_temp = $.create("fake_admin_user_group_list_template_rendered");
mock_template("settings/admin_user_group_list.hbs", false, (args) => { mock_template("settings/admin_user_group_list.hbs", false, (args) => {
assert.equal(args.user_group.id, 1); assert.equal(args.user_group.id, 1);
assert.equal(args.user_group.name, "Mobile"); assert.equal(args.user_group.name, "Mobile");
assert.equal(args.user_group.description, "All mobile people"); assert.equal(args.user_group.description, "All mobile people");
templates_render_called = true; templates_render_called = true;
return fake_rendered_temp; return $fake_rendered_temp;
}); });
let user_groups_list_append_called = false; let user_groups_list_append_called = false;
$("#user-groups").append = (rendered_temp) => { $("#user-groups").append = (rendered_temp) => {
assert.equal(rendered_temp, fake_rendered_temp); assert.equal(rendered_temp, $fake_rendered_temp);
user_groups_list_append_called = true; user_groups_list_append_called = true;
}; };
@@ -158,7 +158,7 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
const all_pills = new Map(); const all_pills = new Map();
const pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`); const $pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`);
pills.appendValidatedData = (item) => { pills.appendValidatedData = (item) => {
const id = item.user_id; const id = item.user_id;
assert.ok(!all_pills.has(id)); assert.ok(!all_pills.has(id));
@@ -171,11 +171,11 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
text_cleared = true; text_cleared = true;
}; };
const input_field_stub = $.create("fake-input-field"); const $input_field_stub = $.create("fake-input-field");
pill_container_stub.children = () => input_field_stub; $pill_container_stub.children = () => $input_field_stub;
let input_typeahead_called = false; let input_typeahead_called = false;
input_field_stub.typeahead = (config) => { $input_field_stub.typeahead = (config) => {
assert.equal(config.items, 5); assert.equal(config.items, 5);
assert.ok(config.fixed); assert.ok(config.fixed);
assert.ok(config.dropup); assert.ok(config.dropup);
@@ -187,9 +187,9 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
assert.equal(typeof config.updater, "function"); assert.equal(typeof config.updater, "function");
(function test_highlighter() { (function test_highlighter() {
const fake_person = $.create("fake-person"); const $fake_person = $.create("fake-person");
typeahead_helper.render_person = () => fake_person; typeahead_helper.render_person = () => $fake_person;
assert.equal(config.highlighter(), fake_person); assert.equal(config.highlighter(), $fake_person);
})(); })();
const fake_context = { const fake_context = {
@@ -236,7 +236,7 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
})(); })();
(function test_updater() { (function test_updater() {
input_field_stub.text("@ali"); $input_field_stub.text("@ali");
user_groups.get_user_group_from_id = () => realm_user_group; user_groups.get_user_group_from_id = () => realm_user_group;
let saved_fade_out_called = false; let saved_fade_out_called = false;
@@ -334,7 +334,7 @@ test_ui("populate_user_groups", ({override_rewire, mock_template}) => {
handler(); handler();
}; };
reset_test_setup(pill_container_stub); reset_test_setup($pill_container_stub);
settings_user_groups.set_up(); settings_user_groups.set_up();
assert.ok(templates_render_called); assert.ok(templates_render_called);
assert.ok(user_groups_list_append_called); assert.ok(user_groups_list_append_called);
@@ -386,63 +386,63 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
$.clear_all_elements(); $.clear_all_elements();
let user_group_find_called = 0; let user_group_find_called = 0;
const user_group_stub = $(`div.user-group[id="${CSS.escape(1)}"]`); const $user_group_stub = $(`div.user-group[id="${CSS.escape(1)}"]`);
const name_field_stub = $.create("fake-name-field"); const $name_field_stub = $.create("fake-name-field");
const description_field_stub = $.create("fake-description-field"); const $description_field_stub = $.create("fake-description-field");
const input_stub = $.create("fake-input"); const $input_stub = $.create("fake-input");
user_group_stub.find = (elem) => { $user_group_stub.find = (elem) => {
if (elem === ".name") { if (elem === ".name") {
user_group_find_called += 1; user_group_find_called += 1;
return name_field_stub; return $name_field_stub;
} }
if (elem === ".description") { if (elem === ".description") {
user_group_find_called += 1; user_group_find_called += 1;
return description_field_stub; return $description_field_stub;
} }
throw new Error(`Unknown element ${elem}`); throw new Error(`Unknown element ${elem}`);
}; };
const pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`); const $pill_container_stub = $(`.pill-container[data-group-pills="${CSS.escape(1)}"]`);
const pill_stub = $.create("fake-pill"); const $pill_stub = $.create("fake-pill");
let pill_container_find_called = 0; let pill_container_find_called = 0;
pill_container_stub.find = (elem) => { $pill_container_stub.find = (elem) => {
if (elem === ".input") { if (elem === ".input") {
pill_container_find_called += 1; pill_container_find_called += 1;
return input_stub; return $input_stub;
} }
if (elem === ".pill") { if (elem === ".pill") {
pill_container_find_called += 1; pill_container_find_called += 1;
return pill_stub; return $pill_stub;
} }
throw new Error(`Unknown element ${elem}`); throw new Error(`Unknown element ${elem}`);
}; };
input_stub.css = (property, val) => { $input_stub.css = (property, val) => {
assert.equal(property, "display"); assert.equal(property, "display");
assert.equal(val, "none"); assert.equal(val, "none");
}; };
// Test the 'off' handlers on the pill-container // Test the 'off' handlers on the pill-container
const turned_off = {}; const turned_off = {};
pill_container_stub.off = (event_name, sel = "whole") => { $pill_container_stub.off = (event_name, sel = "whole") => {
turned_off[event_name + "/" + sel] = true; turned_off[event_name + "/" + sel] = true;
}; };
const exit_button = $.create("fake-pill-exit"); const $exit_button = $.create("fake-pill-exit");
pill_stub.set_find_results(".exit", exit_button); $pill_stub.set_find_results(".exit", $exit_button);
let exit_button_called = false; let exit_button_called = false;
exit_button.css = (property, value) => { $exit_button.css = (property, value) => {
exit_button_called = true; exit_button_called = true;
assert.equal(property, "opacity"); assert.equal(property, "opacity");
assert.equal(value, "0.5"); assert.equal(value, "0.5");
}; };
// We return noop because these are already tested, so we skip them // We return noop because these are already tested, so we skip them
pill_container_stub.children = () => noop; $pill_container_stub.children = () => noop;
$("#user-groups").append = () => noop; $("#user-groups").append = () => noop;
reset_test_setup(pill_container_stub); reset_test_setup($pill_container_stub);
settings_user_groups.set_up(); settings_user_groups.set_up();
@@ -451,8 +451,8 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
// Test different handlers with an external user // Test different handlers with an external user
const delete_handler = $("#user-groups").get_on_handler("click", ".delete"); const delete_handler = $("#user-groups").get_on_handler("click", ".delete");
const fake_delete = $.create("fk-#user-groups.delete_btn"); const $fake_delete = $.create("fk-#user-groups.delete_btn");
fake_delete.set_parents_result(".user-group", $(".user-group")); $fake_delete.set_parents_result(".user-group", $(".user-group"));
set_parents_result_called += 1; set_parents_result_called += 1;
$(".user-group").attr("id", "1"); $(".user-group").attr("id", "1");
set_attributes_called += 1; set_attributes_called += 1;
@@ -470,11 +470,11 @@ test_ui("with_external_user", ({override_rewire, mock_template}) => {
const event = { const event = {
stopPropagation: noop, stopPropagation: noop,
}; };
const pill_mouseenter_handler = pill_stub.get_on_handler("mouseenter"); const pill_mouseenter_handler = $pill_stub.get_on_handler("mouseenter");
const pill_click_handler = pill_container_stub.get_on_handler("click"); const pill_click_handler = $pill_container_stub.get_on_handler("click");
pill_mouseenter_handler(event); pill_mouseenter_handler(event);
pill_click_handler(event); pill_click_handler(event);
assert.equal(delete_handler.call(fake_delete), undefined); assert.equal(delete_handler.call($fake_delete), undefined);
assert.equal(name_update_handler(), undefined); assert.equal(name_update_handler(), undefined);
assert.equal(des_update_handler(), undefined); assert.equal(des_update_handler(), undefined);
assert.equal(member_change_handler(), undefined); assert.equal(member_change_handler(), undefined);
@@ -524,7 +524,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
stopPropagation: noop, stopPropagation: noop,
preventDefault: noop, preventDefault: noop,
}; };
const fake_this = $.create("fake-form.admin-user-group-form"); const $fake_this = $.create("fake-form.admin-user-group-form");
const fake_object_array = [ const fake_object_array = [
{ {
name: "fake-name", name: "fake-name",
@@ -535,7 +535,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
value: "fake-value", value: "fake-value",
}, },
]; ];
fake_this.serializeArray = () => fake_object_array; $fake_this.serializeArray = () => fake_object_array;
channel.post = (opts) => { channel.post = (opts) => {
const data = { const data = {
members: "[null]", members: "[null]",
@@ -577,13 +577,13 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
})(); })();
}; };
handler.call(fake_this, event); handler.call($fake_this, event);
})(); })();
(function test_user_groups_delete_click_triggered() { (function test_user_groups_delete_click_triggered() {
const handler = $("#user-groups").get_on_handler("click", ".delete"); const handler = $("#user-groups").get_on_handler("click", ".delete");
const fake_this = $.create("fake-#user-groups.delete_btn"); const $fake_this = $.create("fake-#user-groups.delete_btn");
fake_this.set_parents_result(".user-group", $(".user-group")); $fake_this.set_parents_result(".user-group", $(".user-group"));
$(".user-group").attr("id", "1"); $(".user-group").attr("id", "1");
channel.del = (opts) => { channel.del = (opts) => {
@@ -593,16 +593,16 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
assert.equal(opts.url, "/json/user_groups/1"); assert.equal(opts.url, "/json/user_groups/1");
assert.deepEqual(opts.data, data); assert.deepEqual(opts.data, data);
fake_this.text($t({defaultMessage: "fake-text"})); $fake_this.text($t({defaultMessage: "fake-text"}));
opts.error(); opts.error();
assert.equal(fake_this.text(), "translated: Failed!"); assert.equal($fake_this.text(), "translated: Failed!");
}; };
confirm_dialog.launch = (conf) => { confirm_dialog.launch = (conf) => {
conf.on_click(); conf.on_click();
}; };
handler.call(fake_this); handler.call($fake_this);
})(); })();
(function test_user_groups_keypress_enter_triggered() { (function test_user_groups_keypress_enter_triggered() {
@@ -625,9 +625,10 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
api_endpoint_called = true; api_endpoint_called = true;
}; };
channel.patch = noop; channel.patch = noop;
const fake_this = $.create("fake-#user-groups_do_not_blur"); const $fake_this = $.create("fake-#user-groups_do_not_blur");
const event = { const event = {
relatedTarget: fake_this, // FIXME: event.relatedTarget should not be a jQuery object
relatedTarget: $fake_this,
}; };
// Any of the blur_exceptions trigger blur event. // Any of the blur_exceptions trigger blur event.
@@ -645,24 +646,24 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
continue; continue;
} }
api_endpoint_called = false; api_endpoint_called = false;
fake_this.closest = (class_name) => { $fake_this.closest = (class_name) => {
if (class_name === blur_exception || class_name === user_group_selector) { if (class_name === blur_exception || class_name === user_group_selector) {
return [1]; return [1];
} }
return []; return [];
}; };
handler.call(fake_this, event); handler.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
} }
api_endpoint_called = false; api_endpoint_called = false;
fake_this.closest = (class_name) => { $fake_this.closest = (class_name) => {
if (class_name === ".typeahead") { if (class_name === ".typeahead") {
return [1]; return [1];
} }
return []; return [];
}; };
handler.call(fake_this, event); handler.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
// Cancel button triggers blur event. // Cancel button triggers blur event.
@@ -671,7 +672,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
settings_user_groups_reload_called = true; settings_user_groups_reload_called = true;
}); });
api_endpoint_called = false; api_endpoint_called = false;
fake_this.closest = (class_name) => { $fake_this.closest = (class_name) => {
if ( if (
class_name === ".save-status.btn-danger" || class_name === ".save-status.btn-danger" ||
class_name === user_group_selector class_name === user_group_selector
@@ -680,7 +681,7 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
} }
return []; return [];
}; };
handler.call(fake_this, event); handler.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
assert.ok(settings_user_groups_reload_called); assert.ok(settings_user_groups_reload_called);
} }
@@ -689,10 +690,10 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
(function test_update_cancel_button() { (function test_update_cancel_button() {
const handler_name = $(user_group_selector).get_on_handler("input", ".name"); const handler_name = $(user_group_selector).get_on_handler("input", ".name");
const handler_desc = $(user_group_selector).get_on_handler("input", ".description"); const handler_desc = $(user_group_selector).get_on_handler("input", ".description");
const sib_des = $(description_selector); const $sib_des = $(description_selector);
const sib_name = $(name_selector); const $sib_name = $(name_selector);
sib_name.text($t({defaultMessage: "mobile"})); $sib_name.text($t({defaultMessage: "mobile"}));
sib_des.text($t({defaultMessage: "All mobile members"})); $sib_des.text($t({defaultMessage: "All mobile members"}));
const group_data = { const group_data = {
name: "translated: mobile", name: "translated: mobile",
@@ -712,8 +713,8 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
}; };
// Cancel button removed if user group if user group has no changes. // Cancel button removed if user group if user group has no changes.
const fake_this = $.create("fake-#update_cancel_button"); const $fake_this = $.create("fake-#update_cancel_button");
handler_name.call(fake_this); handler_name.call($fake_this);
assert.ok(cancel_fade_out_called); assert.ok(cancel_fade_out_called);
assert.ok(instructions_fade_out_called); assert.ok(instructions_fade_out_called);
@@ -721,14 +722,14 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
$(user_group_selector + " .user-group-status").show(); $(user_group_selector + " .user-group-status").show();
cancel_fade_out_called = false; cancel_fade_out_called = false;
instructions_fade_out_called = false; instructions_fade_out_called = false;
handler_name.call(fake_this); handler_name.call($fake_this);
assert.ok(cancel_fade_out_called); assert.ok(cancel_fade_out_called);
assert.ok(instructions_fade_out_called); assert.ok(instructions_fade_out_called);
// Check for handler_desc to achieve 100% coverage. // Check for handler_desc to achieve 100% coverage.
cancel_fade_out_called = false; cancel_fade_out_called = false;
instructions_fade_out_called = false; instructions_fade_out_called = false;
handler_desc.call(fake_this); handler_desc.call($fake_this);
assert.ok(cancel_fade_out_called); assert.ok(cancel_fade_out_called);
assert.ok(instructions_fade_out_called); assert.ok(instructions_fade_out_called);
})(); })();
@@ -736,10 +737,10 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
(function test_user_groups_save_group_changes_triggered() { (function test_user_groups_save_group_changes_triggered() {
const handler_name = $(user_group_selector).get_on_handler("blur", ".name"); const handler_name = $(user_group_selector).get_on_handler("blur", ".name");
const handler_desc = $(user_group_selector).get_on_handler("blur", ".description"); const handler_desc = $(user_group_selector).get_on_handler("blur", ".description");
const sib_des = $(description_selector); const $sib_des = $(description_selector);
const sib_name = $(name_selector); const $sib_name = $(name_selector);
sib_name.text($t({defaultMessage: "mobile"})); $sib_name.text($t({defaultMessage: "mobile"}));
sib_des.text($t({defaultMessage: "All mobile members"})); $sib_des.text($t({defaultMessage: "All mobile members"}));
const group_data = {members: new Set([2, 31])}; const group_data = {members: new Set([2, 31])};
user_groups.get_user_group_from_id = () => group_data; user_groups.get_user_group_from_id = () => group_data;
@@ -782,46 +783,47 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
assert.ok(saved_fade_to_called); assert.ok(saved_fade_to_called);
})(); })();
(function test_post_error() { (function test_post_error() {
const user_group_error = $(user_group_selector + " .user-group-status"); const $user_group_error = $(user_group_selector + " .user-group-status");
user_group_error.show(); $user_group_error.show();
ui_report.error = (error_msg, error_obj, ele) => { ui_report.error = (error_msg, error_obj, ele) => {
const xhr = { const xhr = {
responseText: '{"msg":"fake-msg"}', responseText: '{"msg":"fake-msg"}',
}; };
assert.equal(error_msg, "translated HTML: Failed"); assert.equal(error_msg, "translated HTML: Failed");
assert.deepEqual(error_obj, xhr); assert.deepEqual(error_obj, xhr);
assert.equal(ele, user_group_error); assert.equal(ele, $user_group_error);
}; };
const xhr = { const xhr = {
responseText: '{"msg":"fake-msg", "attrib":"val"}', responseText: '{"msg":"fake-msg", "attrib":"val"}',
}; };
opts.error(xhr); opts.error(xhr);
assert.ok(user_group_error.visible()); assert.ok($user_group_error.visible());
})(); })();
}; };
const fake_this = $.create("fake-#user-groups_blur_name"); const $fake_this = $.create("fake-#user-groups_blur_name");
fake_this.closest = () => []; $fake_this.closest = () => [];
fake_this.set_parents_result(user_group_selector, $(user_group_selector)); $fake_this.set_parents_result(user_group_selector, $(user_group_selector));
const event = { const event = {
relatedTarget: fake_this, // FIXME: event.relatedTarget should not be a jQuery object
relatedTarget: $fake_this,
}; };
api_endpoint_called = false; api_endpoint_called = false;
handler_name.call(fake_this, event); handler_name.call($fake_this, event);
assert.ok(api_endpoint_called); assert.ok(api_endpoint_called);
// Check API endpoint isn't called if name and desc haven't changed. // Check API endpoint isn't called if name and desc haven't changed.
group_data.name = "translated: mobile"; group_data.name = "translated: mobile";
group_data.description = "translated: All mobile members"; group_data.description = "translated: All mobile members";
api_endpoint_called = false; api_endpoint_called = false;
handler_name.call(fake_this, event); handler_name.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
// Check for handler_desc to achieve 100% coverage. // Check for handler_desc to achieve 100% coverage.
api_endpoint_called = false; api_endpoint_called = false;
handler_desc.call(fake_this, event); handler_desc.call($fake_this, event);
assert.ok(!api_endpoint_called); assert.ok(!api_endpoint_called);
})(); })();
@@ -869,15 +871,16 @@ test_ui("on_events", ({override_rewire, mock_template}) => {
})(); })();
}; };
const fake_this = $.create("fake-#user-groups_blur_input"); const $fake_this = $.create("fake-#user-groups_blur_input");
fake_this.set_parents_result(user_group_selector, $(user_group_selector)); $fake_this.set_parents_result(user_group_selector, $(user_group_selector));
fake_this.closest = () => []; $fake_this.closest = () => [];
const event = { const event = {
relatedTarget: fake_this, // FIXME: event.relatedTarget should not be a jQuery object
relatedTarget: $fake_this,
}; };
api_endpoint_called = false; api_endpoint_called = false;
handler.call(fake_this, event); handler.call($fake_this, event);
assert.ok(api_endpoint_called); assert.ok(api_endpoint_called);
})(); })();
}); });

View File

@@ -11,30 +11,30 @@ const spoilers = zrequire("spoilers");
// This function is taken from rendered_markdown.js and slightly modified. // This function is taken from rendered_markdown.js and slightly modified.
const $array = (array) => { const $array = (array) => {
const each = (func) => { const each = (func) => {
for (const [index, elem] of array.entries()) { for (const [index, $elem] of array.entries()) {
func.call(this, index, elem); func.call(this, index, $elem);
} }
}; };
return {each}; return {each};
}; };
const get_spoiler_elem = (title) => { const get_spoiler_elem = (title) => {
const block = $.create(`block-${title}`); const $block = $.create(`block-${title}`);
const header = $.create(`header-${title}`); const $header = $.create(`header-${title}`);
const content = $.create(`content-${title}`); const $content = $.create(`content-${title}`);
content.remove = () => {}; $content.remove = () => {};
header.text(title); $header.text(title);
block.set_find_results(".spoiler-header", header); $block.set_find_results(".spoiler-header", $header);
block.set_find_results(".spoiler-content", content); $block.set_find_results(".spoiler-content", $content);
return block; return $block;
}; };
run_test("hide spoilers in notifications", () => { run_test("hide spoilers in notifications", () => {
const root = $.create("root element"); const $root = $.create("root element");
const spoiler_1 = get_spoiler_elem("this is the title"); const $spoiler_1 = get_spoiler_elem("this is the title");
const spoiler_2 = get_spoiler_elem(""); const $spoiler_2 = get_spoiler_elem("");
root.set_find_results(".spoiler-block", $array([spoiler_1, spoiler_2])); $root.set_find_results(".spoiler-block", $array([$spoiler_1, $spoiler_2]));
spoilers.hide_spoilers_in_notification(root); spoilers.hide_spoilers_in_notification($root);
assert.equal(spoiler_1.find(".spoiler-header").text(), "this is the title (…)"); assert.equal($spoiler_1.find(".spoiler-header").text(), "this is the title (…)");
assert.equal(spoiler_2.find(".spoiler-header").text(), "(…)"); assert.equal($spoiler_2.find(".spoiler-header").text(), "(…)");
}); });

View File

@@ -136,32 +136,32 @@ test("update_property", ({override}) => {
// Test desktop notifications // Test desktop notifications
stream_events.update_property(stream_id, "desktop_notifications", true); stream_events.update_property(stream_id, "desktop_notifications", true);
assert.equal(sub.desktop_notifications, true); assert.equal(sub.desktop_notifications, true);
let checkbox = checkbox_for("desktop_notifications"); let $checkbox = checkbox_for("desktop_notifications");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
// Tests audible notifications // Tests audible notifications
stream_events.update_property(stream_id, "audible_notifications", true); stream_events.update_property(stream_id, "audible_notifications", true);
assert.equal(sub.audible_notifications, true); assert.equal(sub.audible_notifications, true);
checkbox = checkbox_for("audible_notifications"); $checkbox = checkbox_for("audible_notifications");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
// Tests push notifications // Tests push notifications
stream_events.update_property(stream_id, "push_notifications", true); stream_events.update_property(stream_id, "push_notifications", true);
assert.equal(sub.push_notifications, true); assert.equal(sub.push_notifications, true);
checkbox = checkbox_for("push_notifications"); $checkbox = checkbox_for("push_notifications");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
// Tests email notifications // Tests email notifications
stream_events.update_property(stream_id, "email_notifications", true); stream_events.update_property(stream_id, "email_notifications", true);
assert.equal(sub.email_notifications, true); assert.equal(sub.email_notifications, true);
checkbox = checkbox_for("email_notifications"); $checkbox = checkbox_for("email_notifications");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
// Tests wildcard_mentions_notify notifications // Tests wildcard_mentions_notify notifications
stream_events.update_property(stream_id, "wildcard_mentions_notify", true); stream_events.update_property(stream_id, "wildcard_mentions_notify", true);
assert.equal(sub.wildcard_mentions_notify, true); assert.equal(sub.wildcard_mentions_notify, true);
checkbox = checkbox_for("wildcard_mentions_notify"); $checkbox = checkbox_for("wildcard_mentions_notify");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
// Test name change // Test name change
{ {
@@ -195,8 +195,8 @@ test("update_property", ({override}) => {
{ {
override(stream_list, "refresh_pinned_or_unpinned_stream", noop); override(stream_list, "refresh_pinned_or_unpinned_stream", noop);
stream_events.update_property(stream_id, "pin_to_top", true); stream_events.update_property(stream_id, "pin_to_top", true);
checkbox = checkbox_for("pin_to_top"); $checkbox = checkbox_for("pin_to_top");
assert.equal(checkbox.prop("checked"), true); assert.equal($checkbox.prop("checked"), true);
} }
// Test stream privacy change event // Test stream privacy change event

View File

@@ -19,7 +19,7 @@ const topic_list = mock_esm("../../static/js/topic_list");
mock_esm("../../static/js/keydown_util", { mock_esm("../../static/js/keydown_util", {
handle: noop, handle: noop,
}); });
mock_esm("../../static/js/ui", {get_scroll_element: (element) => element}); mock_esm("../../static/js/ui", {get_scroll_element: ($element) => $element});
const {Filter} = zrequire("../js/filter"); const {Filter} = zrequire("../js/filter");
const stream_sort = zrequire("stream_sort"); const stream_sort = zrequire("stream_sort");
@@ -47,13 +47,13 @@ const social = {
let num_unread_for_stream; let num_unread_for_stream;
function create_devel_sidebar_row({mock_template}) { function create_devel_sidebar_row({mock_template}) {
const devel_count = $.create("devel-count"); const $devel_count = $.create("devel-count");
const subscription_block = $.create("devel-block"); const $subscription_block = $.create("devel-block");
const sidebar_row = $("<devel sidebar row>"); const $sidebar_row = $("<devel sidebar row>");
sidebar_row.set_find_results(".subscription_block", subscription_block); $sidebar_row.set_find_results(".subscription_block", $subscription_block);
subscription_block.set_find_results(".unread_count", devel_count); $subscription_block.set_find_results(".unread_count", $devel_count);
mock_template("stream_sidebar_row.hbs", false, (data) => { mock_template("stream_sidebar_row.hbs", false, (data) => {
assert.equal(data.uri, "#narrow/stream/100-devel"); assert.equal(data.uri, "#narrow/stream/100-devel");
@@ -62,17 +62,17 @@ function create_devel_sidebar_row({mock_template}) {
num_unread_for_stream = 42; num_unread_for_stream = 42;
stream_list.create_sidebar_row(devel); stream_list.create_sidebar_row(devel);
assert.equal(devel_count.text(), "42"); assert.equal($devel_count.text(), "42");
} }
function create_social_sidebar_row({mock_template}) { function create_social_sidebar_row({mock_template}) {
const social_count = $.create("social-count"); const $social_count = $.create("social-count");
const subscription_block = $.create("social-block"); const $subscription_block = $.create("social-block");
const sidebar_row = $("<social sidebar row>"); const $sidebar_row = $("<social sidebar row>");
sidebar_row.set_find_results(".subscription_block", subscription_block); $sidebar_row.set_find_results(".subscription_block", $subscription_block);
subscription_block.set_find_results(".unread_count", social_count); $subscription_block.set_find_results(".unread_count", $social_count);
mock_template("stream_sidebar_row.hbs", false, (data) => { mock_template("stream_sidebar_row.hbs", false, (data) => {
assert.equal(data.uri, "#narrow/stream/200-social"); assert.equal(data.uri, "#narrow/stream/200-social");
@@ -81,7 +81,7 @@ function create_social_sidebar_row({mock_template}) {
num_unread_for_stream = 99; num_unread_for_stream = 99;
stream_list.create_sidebar_row(social); stream_list.create_sidebar_row(social);
assert.equal(social_count.text(), "99"); assert.equal($social_count.text(), "99");
} }
function test_ui(label, f) { function test_ui(label, f) {
@@ -105,8 +105,8 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
create_social_sidebar_row({mock_template}); create_social_sidebar_row({mock_template});
const split = '<hr class="stream-split">'; const split = '<hr class="stream-split">';
const devel_sidebar = $("<devel sidebar row>"); const $devel_sidebar = $("<devel sidebar row>");
const social_sidebar = $("<social sidebar row>"); const $social_sidebar = $("<social sidebar row>");
let appended_elems; let appended_elems;
$("#stream_filters").append = (elems) => { $("#stream_filters").append = (elems) => {
@@ -123,20 +123,20 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
assert.ok(topic_list_cleared); assert.ok(topic_list_cleared);
const expected_elems = [ const expected_elems = [
devel_sidebar, // pinned $devel_sidebar, // pinned
split, // separator split, // separator
social_sidebar, // not pinned $social_sidebar, // not pinned
]; ];
assert.deepEqual(appended_elems, expected_elems); assert.deepEqual(appended_elems, expected_elems);
const social_li = $("<social sidebar row>"); const $social_li = $("<social sidebar row>");
const stream_id = social.stream_id; const stream_id = social.stream_id;
social_li.length = 0; $social_li.length = 0;
const privacy_elem = $.create("privacy-stub"); const $privacy_elem = $.create("privacy-stub");
social_li.set_find_results(".stream-privacy", privacy_elem); $social_li.set_find_results(".stream-privacy", $privacy_elem);
social.invite_only = true; social.invite_only = true;
social.color = "#222222"; social.color = "#222222";
@@ -147,25 +147,25 @@ test_ui("create_sidebar_row", ({override_rewire, mock_template}) => {
return "<div>privacy-html"; return "<div>privacy-html";
}); });
stream_list.redraw_stream_privacy(social); stream_list.redraw_stream_privacy(social);
assert.equal(privacy_elem.html(), "<div>privacy-html"); assert.equal($privacy_elem.html(), "<div>privacy-html");
stream_list.set_in_home_view(stream_id, false); stream_list.set_in_home_view(stream_id, false);
assert.ok(social_li.hasClass("out_of_home_view")); assert.ok($social_li.hasClass("out_of_home_view"));
stream_list.set_in_home_view(stream_id, true); stream_list.set_in_home_view(stream_id, true);
assert.ok(!social_li.hasClass("out_of_home_view")); assert.ok(!$social_li.hasClass("out_of_home_view"));
const row = stream_list.stream_sidebar.get_row(stream_id); const row = stream_list.stream_sidebar.get_row(stream_id);
override_rewire(stream_data, "is_active", () => true); override_rewire(stream_data, "is_active", () => true);
row.update_whether_active(); row.update_whether_active();
assert.ok(!social_li.hasClass("inactive_stream")); assert.ok(!$social_li.hasClass("inactive_stream"));
override_rewire(stream_data, "is_active", () => false); override_rewire(stream_data, "is_active", () => false);
row.update_whether_active(); row.update_whether_active();
assert.ok(social_li.hasClass("inactive_stream")); assert.ok($social_li.hasClass("inactive_stream"));
let removed; let removed;
social_li.remove = () => { $social_li.remove = () => {
removed = true; removed = true;
}; };
@@ -183,33 +183,33 @@ test_ui("pinned_streams_never_inactive", ({override_rewire, mock_template}) => {
create_social_sidebar_row({mock_template}); create_social_sidebar_row({mock_template});
// non-pinned streams can be made inactive // non-pinned streams can be made inactive
const social_sidebar = $("<social sidebar row>"); const $social_sidebar = $("<social sidebar row>");
let stream_id = social.stream_id; let stream_id = social.stream_id;
let row = stream_list.stream_sidebar.get_row(stream_id); let row = stream_list.stream_sidebar.get_row(stream_id);
override_rewire(stream_data, "is_active", () => false); override_rewire(stream_data, "is_active", () => false);
stream_list.build_stream_list(); stream_list.build_stream_list();
assert.ok(social_sidebar.hasClass("inactive_stream")); assert.ok($social_sidebar.hasClass("inactive_stream"));
override_rewire(stream_data, "is_active", () => true); override_rewire(stream_data, "is_active", () => true);
row.update_whether_active(); row.update_whether_active();
assert.ok(!social_sidebar.hasClass("inactive_stream")); assert.ok(!$social_sidebar.hasClass("inactive_stream"));
override_rewire(stream_data, "is_active", () => false); override_rewire(stream_data, "is_active", () => false);
row.update_whether_active(); row.update_whether_active();
assert.ok(social_sidebar.hasClass("inactive_stream")); assert.ok($social_sidebar.hasClass("inactive_stream"));
// pinned streams can never be made inactive // pinned streams can never be made inactive
const devel_sidebar = $("<devel sidebar row>"); const $devel_sidebar = $("<devel sidebar row>");
stream_id = devel.stream_id; stream_id = devel.stream_id;
row = stream_list.stream_sidebar.get_row(stream_id); row = stream_list.stream_sidebar.get_row(stream_id);
override_rewire(stream_data, "is_active", () => false); override_rewire(stream_data, "is_active", () => false);
stream_list.build_stream_list(); stream_list.build_stream_list();
assert.ok(!devel_sidebar.hasClass("inactive_stream")); assert.ok(!$devel_sidebar.hasClass("inactive_stream"));
row.update_whether_active(); row.update_whether_active();
assert.ok(!devel_sidebar.hasClass("inactive_stream")); assert.ok(!$devel_sidebar.hasClass("inactive_stream"));
}); });
function add_row(sub) { function add_row(sub) {
@@ -218,11 +218,11 @@ function add_row(sub) {
update_whether_active() {}, update_whether_active() {},
get_li() { get_li() {
const html = "<" + sub.name + " sidebar row html>"; const html = "<" + sub.name + " sidebar row html>";
const obj = $(html); const $obj = $(html);
obj.length = 1; // bypass blueslip error $obj.length = 1; // bypass blueslip error
return obj; return $obj;
}, },
}; };
stream_list.stream_sidebar.set_row(sub.stream_id, row); stream_list.stream_sidebar.set_row(sub.stream_id, row);
@@ -293,30 +293,30 @@ function elem($obj) {
} }
test_ui("zoom_in_and_zoom_out", () => { test_ui("zoom_in_and_zoom_out", () => {
const label1 = $.create("label1 stub"); const $label1 = $.create("label1 stub");
const label2 = $.create("label2 stub"); const $label2 = $.create("label2 stub");
label1.show(); $label1.show();
label2.show(); $label2.show();
assert.ok(label1.visible()); assert.ok($label1.visible());
assert.ok(label2.visible()); assert.ok($label2.visible());
$.create(".stream-filters-label", { $.create(".stream-filters-label", {
children: [elem(label1), elem(label2)], children: [elem($label1), elem($label2)],
}); });
const splitter = $.create("hr stub"); const $splitter = $.create("hr stub");
splitter.show(); $splitter.show();
assert.ok(splitter.visible()); assert.ok($splitter.visible());
$.create(".stream-split", { $.create(".stream-split", {
children: [elem(splitter)], children: [elem($splitter)],
}); });
const stream_li1 = $.create("stream1 stub"); const $stream_li1 = $.create("stream1 stub");
const stream_li2 = $.create("stream2 stub"); const $stream_li2 = $.create("stream2 stub");
function make_attr(arg) { function make_attr(arg) {
return (sel) => { return (sel) => {
@@ -325,12 +325,12 @@ test_ui("zoom_in_and_zoom_out", () => {
}; };
} }
stream_li1.attr = make_attr("42"); $stream_li1.attr = make_attr("42");
stream_li1.hide(); $stream_li1.hide();
stream_li2.attr = make_attr("99"); $stream_li2.attr = make_attr("99");
$.create("#stream_filters li.narrow-filter", { $.create("#stream_filters li.narrow-filter", {
children: [elem(stream_li1), elem(stream_li2)], children: [elem($stream_li1), elem($stream_li2)],
}); });
$("#stream-filters-container")[0] = { $("#stream-filters-container")[0] = {
@@ -340,26 +340,26 @@ test_ui("zoom_in_and_zoom_out", () => {
stream_list.zoom_in_topics({stream_id: 42}); stream_list.zoom_in_topics({stream_id: 42});
assert.ok(!label1.visible()); assert.ok(!$label1.visible());
assert.ok(!label2.visible()); assert.ok(!$label2.visible());
assert.ok(!splitter.visible()); assert.ok(!$splitter.visible());
assert.ok(stream_li1.visible()); assert.ok($stream_li1.visible());
assert.ok(!stream_li2.visible()); assert.ok(!$stream_li2.visible());
assert.ok($("#streams_list").hasClass("zoom-in")); assert.ok($("#streams_list").hasClass("zoom-in"));
$("#stream_filters li.narrow-filter").show = () => { $("#stream_filters li.narrow-filter").show = () => {
stream_li1.show(); $stream_li1.show();
stream_li2.show(); $stream_li2.show();
}; };
stream_li1.length = 1; $stream_li1.length = 1;
stream_list.zoom_out_topics({stream_li: stream_li1}); stream_list.zoom_out_topics({$stream_li: $stream_li1});
assert.ok(label1.visible()); assert.ok($label1.visible());
assert.ok(label2.visible()); assert.ok($label2.visible());
assert.ok(splitter.visible()); assert.ok($splitter.visible());
assert.ok(stream_li1.visible()); assert.ok($stream_li1.visible());
assert.ok(stream_li2.visible()); assert.ok($stream_li2.visible());
assert.ok($("#streams_list").hasClass("zoom-out")); assert.ok($("#streams_list").hasClass("zoom-out"));
}); });
@@ -591,8 +591,8 @@ test_ui("rename_stream", ({override_rewire, mock_template}) => {
stream_data.rename_sub(sub, new_name); stream_data.rename_sub(sub, new_name);
const li_stub = $.create("li stub"); const $li_stub = $.create("li stub");
li_stub.length = 0; $li_stub.length = 0;
mock_template("stream_sidebar_row.hbs", false, (payload) => { mock_template("stream_sidebar_row.hbs", false, (payload) => {
assert.deepEqual(payload, { assert.deepEqual(payload, {
@@ -606,12 +606,12 @@ test_ui("rename_stream", ({override_rewire, mock_template}) => {
pin_to_top: true, pin_to_top: true,
dark_background: payload.dark_background, dark_background: payload.dark_background,
}); });
return {to_$: () => li_stub}; return {to_$: () => $li_stub};
}); });
let count_updated; let count_updated;
override_rewire(stream_list, "update_count_in_dom", (li) => { override_rewire(stream_list, "update_count_in_dom", ($li) => {
assert.equal(li, li_stub); assert.equal($li, $li_stub);
count_updated = true; count_updated = true;
}); });
@@ -638,17 +638,17 @@ test_ui("refresh_pin", ({override_rewire, mock_template}) => {
pin_to_top: true, pin_to_top: true,
}; };
const li_stub = $.create("li stub"); const $li_stub = $.create("li stub");
li_stub.length = 0; $li_stub.length = 0;
mock_template("stream_sidebar_row.hbs", false, () => ({to_$: () => li_stub})); mock_template("stream_sidebar_row.hbs", false, () => ({to_$: () => $li_stub}));
override_rewire(stream_list, "update_count_in_dom", noop); override_rewire(stream_list, "update_count_in_dom", noop);
$("#stream_filters").append = noop; $("#stream_filters").append = noop;
let scrolled; let scrolled;
override_rewire(stream_list, "scroll_stream_into_view", (li) => { override_rewire(stream_list, "scroll_stream_into_view", ($li) => {
assert.equal(li, li_stub); assert.equal($li, $li_stub);
scrolled = true; scrolled = true;
}); });

View File

@@ -64,32 +64,32 @@ function clear_search_input() {
run_test("basics", ({override_rewire}) => { run_test("basics", ({override_rewire}) => {
let cursor_helper; let cursor_helper;
const input = $(".stream-list-filter"); const $input = $(".stream-list-filter");
const section = $(".stream_search_section"); const $section = $(".stream_search_section");
expand_sidebar(); expand_sidebar();
section.addClass("notdisplayed"); $section.addClass("notdisplayed");
cursor_helper = make_cursor_helper(); cursor_helper = make_cursor_helper();
function verify_expanded() { function verify_expanded() {
assert.ok(!section.hasClass("notdisplayed")); assert.ok(!$section.hasClass("notdisplayed"));
simulate_search_expanded(); simulate_search_expanded();
} }
function verify_focused() { function verify_focused() {
assert.ok(stream_list.searching()); assert.ok(stream_list.searching());
assert.ok(input.is_focused()); assert.ok($input.is_focused());
} }
function verify_blurred() { function verify_blurred() {
assert.ok(stream_list.searching()); assert.ok(stream_list.searching());
assert.ok(input.is_focused()); assert.ok($input.is_focused());
} }
function verify_collapsed() { function verify_collapsed() {
assert.ok(section.hasClass("notdisplayed")); assert.ok($section.hasClass("notdisplayed"));
assert.ok(!input.is_focused()); assert.ok(!$input.is_focused());
assert.ok(!stream_list.searching()); assert.ok(!stream_list.searching());
simulate_search_collapsed(); simulate_search_collapsed();
} }
@@ -126,7 +126,7 @@ run_test("basics", ({override_rewire}) => {
(function add_some_text_and_collapse() { (function add_some_text_and_collapse() {
cursor_helper = make_cursor_helper(); cursor_helper = make_cursor_helper();
input.val("foo"); $input.val("foo");
verify_list_updated(() => { verify_list_updated(() => {
toggle_filter(); toggle_filter();
}); });
@@ -149,7 +149,7 @@ run_test("basics", ({override_rewire}) => {
stream_list.initiate_search(); stream_list.initiate_search();
// Clear a non-empty search. // Clear a non-empty search.
input.val("foo"); $input.val("foo");
verify_list_updated(() => { verify_list_updated(() => {
clear_search_input(); clear_search_input();
}); });
@@ -160,7 +160,7 @@ run_test("basics", ({override_rewire}) => {
stream_list.initiate_search(); stream_list.initiate_search();
// Escape a non-empty search. // Escape a non-empty search.
input.val("foo"); $input.val("foo");
stream_list.escape_search(); stream_list.escape_search();
verify_blurred(); verify_blurred();
@@ -169,7 +169,7 @@ run_test("basics", ({override_rewire}) => {
stream_list.initiate_search(); stream_list.initiate_search();
// Escape an empty search. // Escape an empty search.
input.val(""); $input.val("");
stream_list.escape_search(); stream_list.escape_search();
verify_collapsed(); verify_collapsed();
}); });

View File

@@ -9,8 +9,8 @@ const $ = require("../zjsunit/zjquery");
const denmark_stream_id = 101; const denmark_stream_id = 101;
const ui = mock_esm("../../static/js/ui", { const ui = mock_esm("../../static/js/ui", {
get_content_element: (element) => element, get_content_element: ($element) => $element,
get_scroll_element: (element) => element, get_scroll_element: ($element) => $element,
}); });
mock_esm("../../static/js/hash_util", { mock_esm("../../static/js/hash_util", {
@@ -103,16 +103,16 @@ run_test("redraw_left_panel", ({mock_template}) => {
$.create("#manage_streams_container .stream-row", {children: sub_stubs}); $.create("#manage_streams_container .stream-row", {children: sub_stubs});
let ui_called = false; let ui_called = false;
ui.reset_scrollbar = (elem) => { ui.reset_scrollbar = ($elem) => {
ui_called = true; ui_called = true;
assert.equal(elem, $("#subscription_overlay .streams-list")); assert.equal($elem, $("#subscription_overlay .streams-list"));
}; };
// Filtering has the side effect of setting the "active" class // Filtering has the side effect of setting the "active" class
// on our current stream, even if it doesn't match the filter. // on our current stream, even if it doesn't match the filter.
const denmark_row = $(`.stream-row[data-stream-id='${CSS.escape(denmark_stream_id)}']`); const $denmark_row = $(`.stream-row[data-stream-id='${CSS.escape(denmark_stream_id)}']`);
// sanity check it's not set to active // sanity check it's not set to active
assert.ok(!denmark_row.hasClass("active")); assert.ok(!$denmark_row.hasClass("active"));
function test_filter(params, expected_streams) { function test_filter(params, expected_streams) {
const stream_ids = stream_settings_ui.redraw_left_panel(params); const stream_ids = stream_settings_ui.redraw_left_panel(params);
@@ -127,7 +127,7 @@ run_test("redraw_left_panel", ({mock_template}) => {
assert.ok(ui_called); assert.ok(ui_called);
// The denmark row is active, even though it's not displayed. // The denmark row is active, even though it's not displayed.
assert.ok(denmark_row.hasClass("active")); assert.ok($denmark_row.hasClass("active"));
// Search with multiple keywords // Search with multiple keywords
test_filter({input: "Denmark, Pol", subscribed_only: false}, [denmark, poland]); test_filter({input: "Denmark, Pol", subscribed_only: false}, [denmark, poland]);

View File

@@ -19,14 +19,14 @@ run_test("scrub_realm", () => {
$.get_initialize_function()(); $.get_initialize_function()();
const click_handler = $("body").get_on_handler("click", ".scrub-realm-button"); const click_handler = $("body").get_on_handler("click", ".scrub-realm-button");
const fake_this = $.create("fake-.scrub-realm-button"); const $fake_this = $.create("fake-.scrub-realm-button");
fake_this.data = (name) => { $fake_this.data = (name) => {
assert.equal(name, "string-id"); assert.equal(name, "string-id");
return "zulip"; return "zulip";
}; };
let submit_form_called = false; let submit_form_called = false;
fake_this.form = { $fake_this.form = {
submit: () => { submit: () => {
submit_form_called = true; submit_form_called = true;
}, },
@@ -36,7 +36,7 @@ run_test("scrub_realm", () => {
}; };
window.prompt = () => "zulip"; window.prompt = () => "zulip";
click_handler.call(fake_this, event); click_handler.call($fake_this, event);
assert.ok(submit_form_called); assert.ok(submit_form_called);
submit_form_called = false; submit_form_called = false;
@@ -45,7 +45,7 @@ run_test("scrub_realm", () => {
window.alert = () => { window.alert = () => {
alert_called = true; alert_called = true;
}; };
click_handler.call(fake_this, event); click_handler.call($fake_this, event);
assert.ok(!submit_form_called); assert.ok(!submit_form_called);
assert.ok(alert_called); assert.ok(alert_called);

View File

@@ -210,20 +210,20 @@ run_test("render_date_renders_time_html", () => {
const expected_html = $t({defaultMessage: "Today"}); const expected_html = $t({defaultMessage: "Today"});
const attrs = {}; const attrs = {};
const span_stub = $("<span />"); const $span_stub = $("<span />");
span_stub.attr = (name, val) => { $span_stub.attr = (name, val) => {
attrs[name] = val; attrs[name] = val;
return span_stub; return $span_stub;
}; };
span_stub.append = (str) => { $span_stub.append = (str) => {
span_stub.html(str); $span_stub.html(str);
return span_stub; return $span_stub;
}; };
const actual = timerender.render_date(message_time, undefined, today); const $actual = timerender.render_date(message_time, undefined, today);
assert.equal(actual.html(), expected_html); assert.equal($actual.html(), expected_html);
assert.equal(attrs["data-tippy-content"], "Friday, April 12, 2019"); assert.equal(attrs["data-tippy-content"], "Friday, April 12, 2019");
assert.equal(attrs.class, "timerender0"); assert.equal(attrs.class, "timerender0");
}); });
@@ -234,12 +234,12 @@ run_test("render_date_renders_time_above_html", () => {
const message_time = today; const message_time = today;
const message_time_above = add(today, {days: -1}); const message_time_above = add(today, {days: -1});
const span_stub = $("<span />"); const $span_stub = $("<span />");
let appended_val; let appended_val;
span_stub.append = (...val) => { $span_stub.append = (...val) => {
appended_val = val; appended_val = val;
return span_stub; return $span_stub;
}; };
const expected = [ const expected = [

View File

@@ -104,12 +104,12 @@ run_test("narrowing", ({override_rewire}) => {
}); });
run_test("update_count_in_dom", () => { run_test("update_count_in_dom", () => {
function make_elem(elem, count_selector) { function make_elem($elem, count_selector) {
const count = $(count_selector); const $count = $(count_selector);
elem.set_find_results(".unread_count", count); $elem.set_find_results(".unread_count", $count);
count.set_parent(elem); $count.set_parent($elem);
return elem; return $elem;
} }
const counts = { const counts = {

View File

@@ -39,7 +39,7 @@ people.add_active_user(levin);
people.add_active_user(kitty); people.add_active_user(kitty);
run_test("render_notifications_for_narrow", ({override_rewire, mock_template}) => { run_test("render_notifications_for_narrow", ({override_rewire, mock_template}) => {
const typing_notifications = $("#typing_notifications"); const $typing_notifications = $("#typing_notifications");
const two_typing_users_ids = [anna.user_id, vronsky.user_id]; const two_typing_users_ids = [anna.user_id, vronsky.user_id];
const three_typing_users_ids = [anna.user_id, vronsky.user_id, levin.user_id]; const three_typing_users_ids = [anna.user_id, vronsky.user_id, levin.user_id];
@@ -51,32 +51,32 @@ run_test("render_notifications_for_narrow", ({override_rewire, mock_template}) =
// should be rendered but not 'Several people are typing…' // should be rendered but not 'Several people are typing…'
override_rewire(typing_events, "get_users_typing_for_narrow", () => two_typing_users_ids); override_rewire(typing_events, "get_users_typing_for_narrow", () => two_typing_users_ids);
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(typing_notifications.visible()); assert.ok($typing_notifications.visible());
assert.ok(typing_notifications.html().includes(`${anna.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${anna.full_name} is typing…`));
assert.ok(typing_notifications.html().includes(`${vronsky.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${vronsky.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes("Several people are typing…")); assert.ok(!$typing_notifications.html().includes("Several people are typing…"));
// Having 3(=MAX_USERS_TO_DISPLAY_NAME) typists should also display only names // Having 3(=MAX_USERS_TO_DISPLAY_NAME) typists should also display only names
override_rewire(typing_events, "get_users_typing_for_narrow", () => three_typing_users_ids); override_rewire(typing_events, "get_users_typing_for_narrow", () => three_typing_users_ids);
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(typing_notifications.visible()); assert.ok($typing_notifications.visible());
assert.ok(typing_notifications.html().includes(`${anna.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${anna.full_name} is typing…`));
assert.ok(typing_notifications.html().includes(`${vronsky.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${vronsky.full_name} is typing…`));
assert.ok(typing_notifications.html().includes(`${levin.full_name} is typing…`)); assert.ok($typing_notifications.html().includes(`${levin.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes("Several people are typing…")); assert.ok(!$typing_notifications.html().includes("Several people are typing…"));
// Having 4(>MAX_USERS_TO_DISPLAY_NAME) typists should display "Several people are typing…" // Having 4(>MAX_USERS_TO_DISPLAY_NAME) typists should display "Several people are typing…"
override_rewire(typing_events, "get_users_typing_for_narrow", () => four_typing_users_ids); override_rewire(typing_events, "get_users_typing_for_narrow", () => four_typing_users_ids);
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(typing_notifications.visible()); assert.ok($typing_notifications.visible());
assert.ok(typing_notifications.html().includes("Several people are typing…")); assert.ok($typing_notifications.html().includes("Several people are typing…"));
assert.ok(!typing_notifications.html().includes(`${anna.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${anna.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${vronsky.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${vronsky.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${levin.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${levin.full_name} is typing…`));
assert.ok(!typing_notifications.html().includes(`${kitty.full_name} is typing…`)); assert.ok(!$typing_notifications.html().includes(`${kitty.full_name} is typing…`));
// #typing_notifications should be hidden when there are no typists. // #typing_notifications should be hidden when there are no typists.
override_rewire(typing_events, "get_users_typing_for_narrow", () => []); override_rewire(typing_events, "get_users_typing_for_narrow", () => []);
typing_events.render_notifications_for_narrow(); typing_events.render_notifications_for_narrow();
assert.ok(!typing_notifications.visible()); assert.ok(!$typing_notifications.visible());
}); });

View File

@@ -36,14 +36,14 @@ function test(label, f) {
} }
test("feature_check", ({override}) => { test("feature_check", ({override}) => {
const upload_button = $.create("upload-button-stub"); const $upload_button = $.create("upload-button-stub");
upload_button.addClass("notdisplayed"); $upload_button.addClass("notdisplayed");
upload.feature_check(upload_button); upload.feature_check($upload_button);
assert.ok(upload_button.hasClass("notdisplayed")); assert.ok($upload_button.hasClass("notdisplayed"));
override(window, "XMLHttpRequest", () => ({upload: true})); override(window, "XMLHttpRequest", () => ({upload: true}));
upload.feature_check(upload_button); upload.feature_check($upload_button);
assert.ok(!upload_button.hasClass("notdisplayed")); assert.ok(!$upload_button.hasClass("notdisplayed"));
}); });
test("get_item", () => { test("get_item", () => {

View File

@@ -194,7 +194,7 @@ test("filter_user_ids", ({override}) => {
}); });
test("click on user header to toggle display", ({override}) => { test("click on user header to toggle display", ({override}) => {
const user_filter = $(".user-list-filter"); const $user_filter = $(".user-list-filter");
override(popovers, "hide_all", () => {}); override(popovers, "hide_all", () => {});
override(popovers, "hide_all_except_sidebars", () => {}); override(popovers, "hide_all_except_sidebars", () => {});
@@ -205,11 +205,11 @@ test("click on user header to toggle display", ({override}) => {
assert.ok(!$("#user_search_section").hasClass("notdisplayed")); assert.ok(!$("#user_search_section").hasClass("notdisplayed"));
user_filter.val("bla"); $user_filter.val("bla");
$("#userlist-header").trigger("click"); $("#userlist-header").trigger("click");
assert.ok($("#user_search_section").hasClass("notdisplayed")); assert.ok($("#user_search_section").hasClass("notdisplayed"));
assert.equal(user_filter.val(), ""); assert.equal($user_filter.val(), "");
$(".user-list-filter").closest = (selector) => { $(".user-list-filter").closest = (selector) => {
assert.equal(selector, ".app-main [class^='column-']"); assert.equal(selector, ".app-main [class^='column-']");

View File

@@ -35,16 +35,16 @@ const sample_events = [
]; ];
let events; let events;
let widget_elem; let $widget_elem;
let is_event_handled; let is_event_handled;
let is_widget_activated; let is_widget_activated;
const fake_poll_widget = { const fake_poll_widget = {
activate(data) { activate(data) {
is_widget_activated = true; is_widget_activated = true;
widget_elem = data.elem; $widget_elem = data.$elem;
assert.ok(widget_elem.hasClass("widget-content")); assert.ok($widget_elem.hasClass("widget-content"));
widget_elem.handle_events = (e) => { $widget_elem.handle_events = (e) => {
is_event_handled = true; is_event_handled = true;
assert.notDeepStrictEqual(e, events); assert.notDeepStrictEqual(e, events);
events.shift(); events.shift();
@@ -65,7 +65,7 @@ const widgetize = zrequire("widgetize");
function test(label, f) { function test(label, f) {
run_test(label, ({override}) => { run_test(label, ({override}) => {
events = [...sample_events]; events = [...sample_events];
widget_elem = undefined; $widget_elem = undefined;
is_event_handled = false; is_event_handled = false;
is_widget_activated = false; is_widget_activated = false;
widgetize.clear_for_testing(); widgetize.clear_for_testing();
@@ -76,10 +76,10 @@ function test(label, f) {
test("activate", ({override}) => { test("activate", ({override}) => {
// Both widgetize.activate and widgetize.handle_event are tested // Both widgetize.activate and widgetize.handle_event are tested
// here to use the "caching" of widgets // here to use the "caching" of widgets
const row = $.create("<stub message row>"); const $row = $.create("<stub message row>");
row.attr("id", "zhome2909"); $row.attr("id", "zhome2909");
const message_content = $.create("#zhome2909"); const $message_content = $.create("#zhome2909");
row.set_find_results(".message_content", message_content); $row.set_find_results(".message_content", $message_content);
let narrow_active; let narrow_active;
override(narrow_state, "active", () => narrow_active); override(narrow_state, "active", () => narrow_active);
@@ -94,16 +94,16 @@ test("activate", ({override}) => {
assert.equal(data.msg_type, "widget"); assert.equal(data.msg_type, "widget");
assert.equal(data.data, "test_data"); assert.equal(data.data, "test_data");
}, },
row, $row,
widget_type: "poll", widget_type: "poll",
}; };
let is_widget_elem_inserted; let is_widget_elem_inserted;
message_content.append = (elem) => { $message_content.append = ($elem) => {
is_widget_elem_inserted = true; is_widget_elem_inserted = true;
assert.equal(elem, widget_elem); assert.equal($elem, $widget_elem);
assert.ok(elem.hasClass("widget-content")); assert.ok($elem.hasClass("widget-content"));
}; };
is_widget_elem_inserted = false; is_widget_elem_inserted = false;
@@ -111,19 +111,19 @@ test("activate", ({override}) => {
is_event_handled = false; is_event_handled = false;
assert.ok(!widgetize.widget_contents.has(opts.message.id)); assert.ok(!widgetize.widget_contents.has(opts.message.id));
message_content.set_find_results(".widget-content", false); $message_content.set_find_results(".widget-content", false);
widgetize.activate(opts); widgetize.activate(opts);
assert.ok(is_widget_elem_inserted); assert.ok(is_widget_elem_inserted);
assert.ok(is_widget_activated); assert.ok(is_widget_activated);
assert.ok(is_event_handled); assert.ok(is_event_handled);
assert.equal(widgetize.widget_contents.get(opts.message.id), widget_elem); assert.equal(widgetize.widget_contents.get(opts.message.id), $widget_elem);
is_widget_elem_inserted = false; is_widget_elem_inserted = false;
is_widget_activated = false; is_widget_activated = false;
is_event_handled = false; is_event_handled = false;
message_content.set_find_results(".widget-content", false); $message_content.set_find_results(".widget-content", false);
widgetize.activate(opts); widgetize.activate(opts);
assert.ok(is_widget_elem_inserted); assert.ok(is_widget_elem_inserted);
@@ -135,7 +135,7 @@ test("activate", ({override}) => {
is_widget_activated = false; is_widget_activated = false;
is_event_handled = false; is_event_handled = false;
message_content.set_find_results(".widget-content", false); $message_content.set_find_results(".widget-content", false);
widgetize.activate(opts); widgetize.activate(opts);
assert.ok(!is_widget_elem_inserted); assert.ok(!is_widget_elem_inserted);
@@ -171,7 +171,7 @@ test("activate", ({override}) => {
message_id: 2001, message_id: 2001,
sender_id: 102, sender_id: 102,
}; };
widget_elem.handle_events = (e) => { $widget_elem.handle_events = (e) => {
is_event_handled = true; is_event_handled = true;
assert.deepEqual(e, [post_activate_event]); assert.deepEqual(e, [post_activate_event]);
}; };
@@ -191,7 +191,7 @@ test("activate", ({override}) => {
}); });
override(message_lists.current, "get_row", (idx) => { override(message_lists.current, "get_row", (idx) => {
assert.equal(idx, 2001); assert.equal(idx, 2001);
return row; return $row;
}); });
widgetize.set_widgets_for_list(); widgetize.set_widgets_for_list();
}); });

View File

@@ -45,28 +45,28 @@ run_test("basics", () => {
// Next, look at how several functions correctly simulate setting // Next, look at how several functions correctly simulate setting
// and getting for you. // and getting for you.
const widget = $("#my-widget"); const $widget = $("#my-widget");
widget.attr("data-employee-id", 42); $widget.attr("data-employee-id", 42);
assert.equal(widget.attr("data-employee-id"), 42); assert.equal($widget.attr("data-employee-id"), 42);
assert.equal(widget.data("employee-id"), 42); assert.equal($widget.data("employee-id"), 42);
widget.data("department-id", 77); $widget.data("department-id", 77);
assert.equal(widget.attr("data-department-id"), 77); assert.equal($widget.attr("data-department-id"), 77);
assert.equal(widget.data("department-id"), 77); assert.equal($widget.data("department-id"), 77);
widget.data("department-name", "hr"); $widget.data("department-name", "hr");
assert.equal(widget.attr("data-department-name"), "hr"); assert.equal($widget.attr("data-department-name"), "hr");
assert.equal(widget.data("department-name"), "hr"); assert.equal($widget.data("department-name"), "hr");
widget.html("<b>hello</b>"); $widget.html("<b>hello</b>");
assert.equal(widget.html(), "<b>hello</b>"); assert.equal($widget.html(), "<b>hello</b>");
widget.prop("title", "My widget"); $widget.prop("title", "My widget");
assert.equal(widget.prop("title"), "My widget"); assert.equal($widget.prop("title"), "My widget");
widget.val("42"); $widget.val("42");
assert.equal(widget.val(), "42"); assert.equal($widget.val(), "42");
}); });
run_test("finding_related_objects", () => { run_test("finding_related_objects", () => {
@@ -84,17 +84,17 @@ run_test("finding_related_objects", () => {
// But you can set up your tests to simulate DOM relationships. // But you can set up your tests to simulate DOM relationships.
// //
// We will use set_find_results(), which is a special zjquery helper. // We will use set_find_results(), which is a special zjquery helper.
const emoji = $('<div class="emoji">'); const $emoji = $('<div class="emoji">');
$("#my-message").set_find_results(".emoji", emoji); $("#my-message").set_find_results(".emoji", $emoji);
// And then calling the function produces the desired effect: // And then calling the function produces the desired effect:
update_message_emoji("foo.png"); update_message_emoji("foo.png");
assert.equal(emoji.attr("src"), "foo.png"); assert.equal($emoji.attr("src"), "foo.png");
// Sometimes you want to deliberately test paths that do not find an // Sometimes you want to deliberately test paths that do not find an
// element. You can pass 'false' as the result for those cases. // element. You can pass 'false' as the result for those cases.
emoji.set_find_results(".random", false); $emoji.set_find_results(".random", false);
assert.equal(emoji.find(".random").length, 0); assert.equal($emoji.find(".random").length, 0);
/* /*
An important thing to understand is that zjquery doesn't truly An important thing to understand is that zjquery doesn't truly
simulate DOM. The way you make relationships work in zjquery simulate DOM. The way you make relationships work in zjquery
@@ -103,12 +103,12 @@ run_test("finding_related_objects", () => {
Here is another example. Here is another example.
*/ */
const my_parents = $("#folder1,#folder4"); const $my_parents = $("#folder1,#folder4");
const elem = $("#folder555"); const $elem = $("#folder555");
elem.set_parents_result(".folder", my_parents); $elem.set_parents_result(".folder", $my_parents);
elem.parents(".folder").addClass("active"); $elem.parents(".folder").addClass("active");
assert.ok(my_parents.hasClass("active")); assert.ok($my_parents.hasClass("active"));
}); });
run_test("clicks", () => { run_test("clicks", () => {
@@ -188,12 +188,12 @@ run_test("create", () => {
// You can create jQuery objects that aren't tied to any particular // You can create jQuery objects that aren't tied to any particular
// selector, and which just have a name. // selector, and which just have a name.
const obj1 = $.create("the table holding employees"); const $obj1 = $.create("the table holding employees");
const obj2 = $.create("the collection of rows in the table"); const $obj2 = $.create("the collection of rows in the table");
obj1.show(); $obj1.show();
assert.ok(obj1.visible()); assert.ok($obj1.visible());
obj2.addClass(".striped"); $obj2.addClass(".striped");
assert.ok(obj2.hasClass(".striped")); assert.ok($obj2.hasClass(".striped"));
}); });

View File

@@ -331,8 +331,8 @@ class CommonUtils {
return false; return false;
} }
const row = zulip_test.last_visible_row(); const $row = zulip_test.last_visible_row();
if (zulip_test.row_id(row) !== last_msg.id) { if (zulip_test.row_id($row) !== last_msg.id) {
return false; return false;
} }
@@ -343,7 +343,7 @@ class CommonUtils {
don't add the star icon until the server don't add the star icon until the server
responds. responds.
*/ */
return row.find(".star").length === 1; return $row.find(".star").length === 1;
}, },
{}, {},
content, content,

View File

@@ -31,8 +31,8 @@ async function copy_messages(
$("body").trigger(new $.Event("keydown", {which: 67, ctrlKey: true})); $("body").trigger(new $.Event("keydown", {which: 67, ctrlKey: true}));
// find temp div with copied text // find temp div with copied text
const temp_div = $("#copytempdiv"); const $temp_div = $("#copytempdiv");
return temp_div return $temp_div
.children("p") .children("p")
.get() .get()
.map((p) => p.textContent!); .map((p) => p.textContent!);

View File

@@ -4,10 +4,10 @@ import common from "../puppeteer_lib/common";
async function click_delete_and_return_last_msg_id(page: Page): Promise<string | undefined> { async function click_delete_and_return_last_msg_id(page: Page): Promise<string | undefined> {
return await page.evaluate(() => { return await page.evaluate(() => {
const msg = $("#zhome .message_row").last(); const $msg = $("#zhome .message_row").last();
msg.find(".message_control_button.actions_hover").trigger("click"); $msg.find(".message_control_button.actions_hover").trigger("click");
$(".delete_message").trigger("click"); $(".delete_message").trigger("click");
return msg.attr("id"); return $msg.attr("id");
}); });
} }

View File

@@ -4,8 +4,8 @@ import common from "../puppeteer_lib/common";
async function trigger_edit_last_message(page: Page): Promise<void> { async function trigger_edit_last_message(page: Page): Promise<void> {
await page.evaluate(() => { await page.evaluate(() => {
const msg = $("#zhome .message_row").last(); const $msg = $("#zhome .message_row").last();
msg.find(".message_control_button.actions_hover").trigger("click"); $msg.find(".message_control_button.actions_hover").trigger("click");
$(".popover_edit_message").trigger("click"); $(".popover_edit_message").trigger("click");
}); });
await page.waitForSelector(".message_edit_content", {visible: true}); await page.waitForSelector(".message_edit_content", {visible: true});

View File

@@ -12,17 +12,17 @@ async function stars_count(page: Page): Promise<number> {
async function toggle_test_star_message(page: Page): Promise<void> { async function toggle_test_star_message(page: Page): Promise<void> {
await page.evaluate((message: string) => { await page.evaluate((message: string) => {
const msg = $(`.message_content:contains("${CSS.escape(message)}"):visible`).last(); const $msg = $(`.message_content:contains("${CSS.escape(message)}"):visible`).last();
if (msg.length !== 1) { if ($msg.length !== 1) {
throw new Error("cannot find test star message"); throw new Error("cannot find test star message");
} }
const star_icon = msg.closest(".messagebox").find(".star"); const $star_icon = $msg.closest(".messagebox").find(".star");
if (star_icon.length !== 1) { if ($star_icon.length !== 1) {
throw new Error("cannot find star icon"); throw new Error("cannot find star icon");
} }
star_icon.trigger("click"); $star_icon.trigger("click");
}, message); }, message);
} }

View File

@@ -188,7 +188,7 @@ exports.mock_cjs = (module_path, obj) => {
}; };
exports.mock_jquery = ($) => { exports.mock_jquery = ($) => {
jquery_function = $; jquery_function = $; // eslint-disable-line no-jquery/variable-pattern
return $; return $;
}; };

View File

@@ -43,8 +43,8 @@ function make_zjquery() {
const fn = {}; const fn = {};
function new_elem(selector, create_opts) { function new_elem(selector, create_opts) {
const elem = FakeElement(selector, {...create_opts}); const $elem = FakeElement(selector, {...create_opts});
Object.assign(elem, fn); Object.assign($elem, fn);
// Create a proxy handler to detect missing stubs. // Create a proxy handler to detect missing stubs.
// //
@@ -76,7 +76,7 @@ function make_zjquery() {
}, },
}; };
const proxy = new Proxy(elem, handler); const proxy = new Proxy($elem, handler);
return proxy; return proxy;
} }
@@ -130,8 +130,8 @@ function make_zjquery() {
verify_selector_for_zulip(selector); verify_selector_for_zulip(selector);
if (!elems.has(selector)) { if (!elems.has(selector)) {
const elem = new_elem(selector); const $elem = new_elem(selector);
elems.set(selector, elem); elems.set(selector, $elem);
} }
return elems.get(selector); return elems.get(selector);
}; };
@@ -146,10 +146,10 @@ function make_zjquery() {
zjquery.create = function (name, opts) { zjquery.create = function (name, opts) {
assert.ok(!elems.has(name), "You already created an object with this name!!"); assert.ok(!elems.has(name), "You already created an object with this name!!");
const elem = new_elem(name, opts); const $elem = new_elem(name, opts);
elems.set(name, elem); elems.set(name, $elem);
return elem; return $elem;
}; };
zjquery.trim = function (s) { zjquery.trim = function (s) {
@@ -250,4 +250,4 @@ const $ = new Proxy(make_zjquery(), {
}, },
}); });
module.exports = $; module.exports = $; // eslint-disable-line no-jquery/variable-pattern

View File

@@ -15,38 +15,38 @@ function FakeElement(selector, opts) {
let height; let height;
const find_results = new Map(); const find_results = new Map();
let my_parent; let $my_parent;
const parents_result = new Map(); const parents_result = new Map();
const properties = new Map(); const properties = new Map();
const attrs = new Map(); const attrs = new Map();
const classes = new Map(); const classes = new Map();
const event_store = make_event_store(selector); const event_store = make_event_store(selector);
const self = { const $self = {
addClass(class_name) { addClass(class_name) {
classes.set(class_name, true); classes.set(class_name, true);
return self; return $self;
}, },
append(arg) { append(arg) {
html = html + arg; html = html + arg;
return self; return $self;
}, },
attr(name, val) { attr(name, val) {
if (val === undefined) { if (val === undefined) {
return attrs.get(name); return attrs.get(name);
} }
attrs.set(name, val); attrs.set(name, val);
return self; return $self;
}, },
data(name, val) { data(name, val) {
if (val === undefined) { if (val === undefined) {
return attrs.get("data-" + name); return attrs.get("data-" + name);
} }
attrs.set("data-" + name, val); attrs.set("data-" + name, val);
return self; return $self;
}, },
delay() { delay() {
return self; return $self;
}, },
debug() { debug() {
return { return {
@@ -59,22 +59,22 @@ function FakeElement(selector, opts) {
if (arg === undefined) { if (arg === undefined) {
find_results.clear(); find_results.clear();
} }
return self; return $self;
}, },
eq() { eq() {
return self; return $self;
}, },
expectOne() { expectOne() {
// silently do nothing // silently do nothing
return self; return $self;
}, },
fadeTo: noop, fadeTo: noop,
find(child_selector) { find(child_selector) {
const child = find_results.get(child_selector); const $child = find_results.get(child_selector);
if (child) { if ($child) {
return child; return $child;
} }
if (child === false) { if ($child === false) {
// This is deliberately set to simulate missing find results. // This is deliberately set to simulate missing find results.
// Return an empty array, the most common check is // Return an empty array, the most common check is
// if ($.find().length) { //success } // if ($.find().length) { //success }
@@ -84,12 +84,12 @@ function FakeElement(selector, opts) {
We need you to simulate the results of $(...).find(...) We need you to simulate the results of $(...).find(...)
by using set_find_results. You want something like this: by using set_find_results. You want something like this:
const container = ...; const $container = ...;
const child = ...; const $child = ...;
container.set_find_results("${child_selector}", child); $container.set_find_results("${child_selector}", $child);
Then calling container.find("${child_selector}") will return Then calling $container.find("${child_selector}") will return
the "child" zjquery element. the "$child" zjquery element.
`); `);
}, },
@@ -107,12 +107,12 @@ function FakeElement(selector, opts) {
}, },
hide() { hide() {
shown = false; shown = false;
return self; return $self;
}, },
html(arg) { html(arg) {
if (arg !== undefined) { if (arg !== undefined) {
html = arg; html = arg;
return self; return $self;
} }
return html; return html;
}, },
@@ -121,9 +121,9 @@ function FakeElement(selector, opts) {
return shown; return shown;
} }
if (arg === ":focus") { if (arg === ":focus") {
return self.is_focused(); return $self.is_focused();
} }
return self; return $self;
}, },
is_focused() { is_focused() {
// is_focused is not a jQuery thing; this is // is_focused is not a jQuery thing; this is
@@ -132,7 +132,7 @@ function FakeElement(selector, opts) {
}, },
off(...args) { off(...args) {
event_store.off(...args); event_store.off(...args);
return self; return $self;
}, },
offset() { offset() {
return { return {
@@ -142,44 +142,44 @@ function FakeElement(selector, opts) {
}, },
on(...args) { on(...args) {
event_store.on(...args); event_store.on(...args);
return self; return $self;
}, },
one(...args) { one(...args) {
event_store.one(...args); event_store.one(...args);
return self; return $self;
}, },
parent() { parent() {
return my_parent; return $my_parent;
}, },
parents(parents_selector) { parents(parents_selector) {
const result = parents_result.get(parents_selector); const $result = parents_result.get(parents_selector);
assert.ok( assert.ok(
result, $result,
"You need to call set_parents_result for " + parents_selector + " in " + selector, "You need to call set_parents_result for " + parents_selector + " in " + selector,
); );
return result; return $result;
}, },
prepend(arg) { prepend(arg) {
html = arg + html; html = arg + html;
return self; return $self;
}, },
prop(name, val) { prop(name, val) {
if (val === undefined) { if (val === undefined) {
return properties.get(name); return properties.get(name);
} }
properties.set(name, val); properties.set(name, val);
return self; return $self;
}, },
removeAttr(name) { removeAttr(name) {
attrs.delete(name); attrs.delete(name);
return self; return $self;
}, },
removeClass(class_names) { removeClass(class_names) {
class_names = class_names.split(" "); class_names = class_names.split(" ");
for (const class_name of class_names) { for (const class_name of class_names) {
classes.delete(class_name); classes.delete(class_name);
} }
return self; return $self;
}, },
remove() { remove() {
throw new Error(` throw new Error(`
@@ -193,68 +193,68 @@ function FakeElement(selector, opts) {
}, },
removeData: noop, removeData: noop,
replaceWith() { replaceWith() {
return self; return $self;
}, },
scrollTop() { scrollTop() {
return self; return $self;
}, },
serializeArray() { serializeArray() {
return self; return $self;
}, },
set_find_results(find_selector, jquery_object) { set_find_results(find_selector, $jquery_object) {
if (jquery_object === undefined) { if ($jquery_object === undefined) {
throw new Error( throw new Error(
"Please make the 'find result' be something like $.create('unused')", "Please make the 'find result' be something like $.create('unused')",
); );
} }
find_results.set(find_selector, jquery_object); find_results.set(find_selector, $jquery_object);
}, },
set_height(fake_height) { set_height(fake_height) {
height = fake_height; height = fake_height;
}, },
set_parent(parent_elem) { set_parent($parent_elem) {
my_parent = parent_elem; $my_parent = $parent_elem;
}, },
set_parents_result(selector, result) { set_parents_result(selector, $result) {
parents_result.set(selector, result); parents_result.set(selector, $result);
}, },
show() { show() {
shown = true; shown = true;
return self; return $self;
}, },
slice() { slice() {
return self; return $self;
}, },
stop() { stop() {
return self; return $self;
}, },
text(...args) { text(...args) {
if (args.length !== 0) { if (args.length !== 0) {
if (args[0] !== undefined) { if (args[0] !== undefined) {
text = args[0].toString(); text = args[0].toString();
} }
return self; return $self;
} }
return text; return text;
}, },
toggle(show) { toggle(show) {
assert.ok([true, false].includes(show)); assert.ok([true, false].includes(show));
shown = show; shown = show;
return self; return $self;
}, },
tooltip() { tooltip() {
return self; return $self;
}, },
trigger(ev) { trigger(ev) {
event_store.trigger(self, ev); event_store.trigger($self, ev);
return self; return $self;
}, },
val(...args) { val(...args) {
if (args.length === 0) { if (args.length === 0) {
return value || ""; return value || "";
} }
[value] = args; [value] = args;
return self; return $self;
}, },
visible() { visible() {
return shown; return shown;
@@ -262,34 +262,34 @@ function FakeElement(selector, opts) {
}; };
if (opts.children) { if (opts.children) {
self.map = (f) => opts.children.map((i, elem) => f(elem, i)); $self.map = (f) => opts.children.map((i, elem) => f(elem, i));
self.each = (f) => { $self.each = (f) => {
for (const child of opts.children) { for (const child of opts.children) {
f.call(child); f.call(child);
} }
}; };
self[Symbol.iterator] = function* () { $self[Symbol.iterator] = function* () {
for (const child of opts.children) { for (const child of opts.children) {
yield child; yield child;
} }
}; };
for (const [i, child] of opts.children.entries()) { for (const [i, child] of opts.children.entries()) {
self[i] = child; $self[i] = child;
} }
self.length = opts.children.length; $self.length = opts.children.length;
} }
if (selector[0] === "<") { if (selector[0] === "<") {
self.html(selector); $self.html(selector);
} }
self.selector = selector; $self.selector = selector;
self.__zjquery = true; $self.__zjquery = true;
return self; return $self;
} }
function make_event_store(selector) { function make_event_store(selector) {
@@ -394,7 +394,8 @@ function make_event_store(selector) {
ev = new FakeEvent(ev); ev = new FakeEvent(ev);
} }
if (!ev.target) { if (!ev.target) {
ev.target = $element; // FIXME: event.target should not be a jQuery object
ev.target = $element; // eslint-disable-line no-jquery/variable-pattern
} }
const func = on_functions.get(ev.type); const func = on_functions.get(ev.type);

View File

@@ -10,7 +10,7 @@ import {page_params} from "./page_params";
export function launch() { export function launch() {
overlays.open_overlay({ overlays.open_overlay({
name: "about-zulip", name: "about-zulip",
overlay: $("#about-zulip"), $overlay: $("#about-zulip"),
on_close() { on_close() {
browser_history.exit_overlay(); browser_history.exit_overlay();
}, },

View File

@@ -59,8 +59,8 @@ function get_pm_list_item(user_id) {
} }
function set_pm_count(user_ids_string, count) { function set_pm_count(user_ids_string, count) {
const pm_li = get_pm_list_item(user_ids_string); const $pm_li = get_pm_list_item(user_ids_string);
ui_util.update_unread_count_in_dom(pm_li, count); ui_util.update_unread_count_in_dom($pm_li, count);
} }
export function update_dom_with_unread_counts(counts) { export function update_dom_with_unread_counts(counts) {
@@ -285,7 +285,7 @@ export function reset_users() {
} }
export function narrow_for_user(opts) { export function narrow_for_user(opts) {
const user_id = buddy_list.get_key_from_li({li: opts.li}); const user_id = buddy_list.get_key_from_li({$li: opts.$li});
return narrow_for_user_id({user_id}); return narrow_for_user_id({user_id});
} }
@@ -324,7 +324,7 @@ export function set_cursor_and_filter() {
$input.on("blur", () => user_cursor.clear()); $input.on("blur", () => user_cursor.clear());
keydown_util.handle({ keydown_util.handle({
elem: $input, $elem: $input,
handlers: { handlers: {
Enter() { Enter() {
keydown_enter_key(); keydown_enter_key();

View File

@@ -34,19 +34,19 @@ function get_text_from_item(item) {
return undefined; return undefined;
} }
function set_up_pill_typeahead({pill_widget, pill_container, get_users}) { function set_up_pill_typeahead({pill_widget, $pill_container, get_users}) {
const opts = { const opts = {
user_source: get_users, user_source: get_users,
stream: true, stream: true,
user_group: true, user_group: true,
user: true, user: true,
}; };
pill_typeahead.set_up(pill_container.find(".input"), pill_widget, opts); pill_typeahead.set_up($pill_container.find(".input"), pill_widget, opts);
} }
export function create({pill_container, get_potential_subscribers}) { export function create({$pill_container, get_potential_subscribers}) {
const pill_widget = input_pill.create({ const pill_widget = input_pill.create({
container: pill_container, $container: $pill_container,
create_item_from_text, create_item_from_text,
get_text_from_item, get_text_from_item,
}); });
@@ -56,7 +56,7 @@ export function create({pill_container, get_potential_subscribers}) {
return user_pill.filter_taken_users(potential_subscribers, pill_widget); return user_pill.filter_taken_users(potential_subscribers, pill_widget);
} }
set_up_pill_typeahead({pill_widget, pill_container, get_users}); set_up_pill_typeahead({pill_widget, $pill_container, get_users});
return pill_widget; return pill_widget;
} }
@@ -70,7 +70,7 @@ function get_pill_user_ids(pill_widget) {
export function set_up_handlers({ export function set_up_handlers({
get_pill_widget, get_pill_widget,
parent_container, $parent_container,
pill_selector, pill_selector,
button_selector, button_selector,
action, action,
@@ -108,14 +108,14 @@ export function set_up_handlers({
action({pill_user_ids}); action({pill_user_ids});
} }
parent_container.on("keyup", pill_selector, (e) => { $parent_container.on("keyup", pill_selector, (e) => {
if (e.key === "Enter") { if (e.key === "Enter") {
e.preventDefault(); e.preventDefault();
callback(); callback();
} }
}); });
parent_container.on("click", button_selector, (e) => { $parent_container.on("click", button_selector, (e) => {
e.preventDefault(); e.preventDefault();
callback(); callback();
}); });

View File

@@ -16,15 +16,15 @@ export function rerender_alert_words_ui() {
const words = alert_words.get_word_list(); const words = alert_words.get_word_list();
words.sort(); words.sort();
const word_list = $("#alert-words-table"); const $word_list = $("#alert-words-table");
ListWidget.create(word_list, words, { ListWidget.create($word_list, words, {
name: "alert-words-list", name: "alert-words-list",
modifier(alert_word) { modifier(alert_word) {
return render_alert_word_settings_item({alert_word}); return render_alert_word_settings_item({alert_word});
}, },
parent_container: $("#alert-word-settings"), $parent_container: $("#alert-word-settings"),
simplebar_container: $("#alert-word-settings .progressive-table-wrapper"), $simplebar_container: $("#alert-word-settings .progressive-table-wrapper"),
}); });
// Focus new alert word name text box. // Focus new alert word name text box.
@@ -32,14 +32,14 @@ export function rerender_alert_words_ui() {
} }
function update_alert_word_status(status_text, is_error) { function update_alert_word_status(status_text, is_error) {
const alert_word_status = $("#alert_word_status"); const $alert_word_status = $("#alert_word_status");
if (is_error) { if (is_error) {
alert_word_status.removeClass("alert-success").addClass("alert-danger"); $alert_word_status.removeClass("alert-success").addClass("alert-danger");
} else { } else {
alert_word_status.removeClass("alert-danger").addClass("alert-success"); $alert_word_status.removeClass("alert-danger").addClass("alert-success");
} }
alert_word_status.find(".alert_word_status_text").text(status_text); $alert_word_status.find(".alert_word_status_text").text(status_text);
alert_word_status.show(); $alert_word_status.show();
} }
function add_alert_word(alert_word) { function add_alert_word(alert_word) {
@@ -114,8 +114,8 @@ export function set_up_alert_words() {
$("#alert-word-settings").on("click", ".close-alert-word-status", (event) => { $("#alert-word-settings").on("click", ".close-alert-word-status", (event) => {
event.preventDefault(); event.preventDefault();
const alert = $(event.currentTarget).parents(".alert"); const $alert = $(event.currentTarget).parents(".alert");
alert.hide(); $alert.hide();
}); });
} }

View File

@@ -50,15 +50,15 @@ function set_upload_space_stats() {
} }
function delete_attachments(attachment) { function delete_attachments(attachment) {
const status = $("#delete-upload-status"); const $status = $("#delete-upload-status");
channel.del({ channel.del({
url: "/json/attachments/" + attachment, url: "/json/attachments/" + attachment,
idempotent: true, idempotent: true,
error(xhr) { error(xhr) {
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, status); ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $status);
}, },
success() { success() {
ui_report.success($t_html({defaultMessage: "Attachment deleted"}), status); ui_report.success($t_html({defaultMessage: "Attachment deleted"}), $status);
}, },
}); });
} }
@@ -86,32 +86,32 @@ function sort_mentioned_in(a, b) {
function render_attachments_ui() { function render_attachments_ui() {
set_upload_space_stats(); set_upload_space_stats();
const uploaded_files_table = $("#uploaded_files_table").expectOne(); const $uploaded_files_table = $("#uploaded_files_table").expectOne();
const $search_input = $("#upload_file_search"); const $search_input = $("#upload_file_search");
ListWidget.create(uploaded_files_table, attachments, { ListWidget.create($uploaded_files_table, attachments, {
name: "uploaded-files-list", name: "uploaded-files-list",
modifier(attachment) { modifier(attachment) {
return render_uploaded_files_list({attachment}); return render_uploaded_files_list({attachment});
}, },
filter: { filter: {
element: $search_input, $element: $search_input,
predicate(item, value) { predicate(item, value) {
return item.name.toLocaleLowerCase().includes(value); return item.name.toLocaleLowerCase().includes(value);
}, },
onupdate() { onupdate() {
ui.reset_scrollbar(uploaded_files_table.closest(".progressive-table-wrapper")); ui.reset_scrollbar($uploaded_files_table.closest(".progressive-table-wrapper"));
}, },
}, },
parent_container: $("#attachments-settings").expectOne(), $parent_container: $("#attachments-settings").expectOne(),
init_sort: ["numeric", "create_time"], init_sort: ["numeric", "create_time"],
sort_fields: { sort_fields: {
mentioned_in: sort_mentioned_in, mentioned_in: sort_mentioned_in,
}, },
simplebar_container: $("#attachments-settings .progressive-table-wrapper"), $simplebar_container: $("#attachments-settings .progressive-table-wrapper"),
}); });
ui.reset_scrollbar(uploaded_files_table.closest(".progressive-table-wrapper")); ui.reset_scrollbar($uploaded_files_table.closest(".progressive-table-wrapper"));
} }
function format_attachment_data(new_attachments) { function format_attachment_data(new_attachments) {
@@ -143,7 +143,7 @@ export function update_attachments(event) {
export function set_up_attachments() { export function set_up_attachments() {
// The settings page must be rendered before this function gets called. // The settings page must be rendered before this function gets called.
const status = $("#delete-upload-status"); const $status = $("#delete-upload-status");
loading.make_indicator($("#attachments_loading_indicator"), {text: "Loading..."}); loading.make_indicator($("#attachments_loading_indicator"), {text: "Loading..."});
$("#uploaded_files_table").on("click", ".remove-attachment", (e) => { $("#uploaded_files_table").on("click", ".remove-attachment", (e) => {
@@ -162,7 +162,7 @@ export function set_up_attachments() {
}, },
error(xhr) { error(xhr) {
loading.destroy_indicator($("#attachments_loading_indicator")); loading.destroy_indicator($("#attachments_loading_indicator"));
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, status); ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $status);
}, },
}); });
} }

View File

@@ -17,36 +17,36 @@ export function build_bot_create_widget() {
return $("#bot_avatar_file_input"); return $("#bot_avatar_file_input");
}; };
const file_name_field = $("#bot_avatar_file"); const $file_name_field = $("#bot_avatar_file");
const input_error = $("#bot_avatar_file_input_error"); const $input_error = $("#bot_avatar_file_input_error");
const clear_button = $("#bot_avatar_clear_button"); const $clear_button = $("#bot_avatar_clear_button");
const upload_button = $("#bot_avatar_upload_button"); const $upload_button = $("#bot_avatar_upload_button");
return upload_widget.build_widget( return upload_widget.build_widget(
get_file_input, get_file_input,
file_name_field, $file_name_field,
input_error, $input_error,
clear_button, $clear_button,
upload_button, $upload_button,
); );
} }
export function build_bot_edit_widget(target) { export function build_bot_edit_widget($target) {
const get_file_input = function () { const get_file_input = function () {
return target.find(".edit_bot_avatar_file_input"); return $target.find(".edit_bot_avatar_file_input");
}; };
const file_name_field = target.find(".edit_bot_avatar_file"); const $file_name_field = $target.find(".edit_bot_avatar_file");
const input_error = target.find(".edit_bot_avatar_error"); const $input_error = $target.find(".edit_bot_avatar_error");
const clear_button = target.find(".edit_bot_avatar_clear_button"); const $clear_button = $target.find(".edit_bot_avatar_clear_button");
const upload_button = target.find(".edit_bot_avatar_upload_button"); const $upload_button = $target.find(".edit_bot_avatar_upload_button");
return upload_widget.build_widget( return upload_widget.build_widget(
get_file_input, get_file_input,
file_name_field, $file_name_field,
input_error, $input_error,
clear_button, $clear_button,
upload_button, $upload_button,
); );
} }

View File

@@ -10,7 +10,7 @@ export function create_ajax_request(
type = "POST", type = "POST",
success_callback, success_callback,
) { ) {
const form = $(`#${CSS.escape(form_name)}-form`); const $form = $(`#${CSS.escape(form_name)}-form`);
const form_loading_indicator = `#${CSS.escape(form_name)}_loading_indicator`; const form_loading_indicator = `#${CSS.escape(form_name)}_loading_indicator`;
const form_input_section = `#${CSS.escape(form_name)}-input-section`; const form_input_section = `#${CSS.escape(form_name)}-input-section`;
const form_success = `#${CSS.escape(form_name)}-success`; const form_success = `#${CSS.escape(form_name)}-success`;
@@ -32,7 +32,7 @@ export function create_ajax_request(
const data = {}; const data = {};
for (const item of form.serializeArray()) { for (const item of $form.serializeArray()) {
if (ignored_inputs.includes(item.name)) { if (ignored_inputs.includes(item.name)) {
continue; continue;
} }

View File

@@ -28,12 +28,12 @@ class BuddyListConf {
get_li_from_key(opts) { get_li_from_key(opts) {
const user_id = opts.key; const user_id = opts.key;
const container = $(this.container_sel); const $container = $(this.container_sel);
return container.find(`${this.item_sel}[data-user-id='${CSS.escape(user_id)}']`); return $container.find(`${this.item_sel}[data-user-id='${CSS.escape(user_id)}']`);
} }
get_key_from_li(opts) { get_key_from_li(opts) {
return Number.parseInt(opts.li.expectOne().attr("data-user-id"), 10); return Number.parseInt(opts.$li.expectOne().attr("data-user-id"), 10);
} }
get_data_from_keys(opts) { get_data_from_keys(opts) {
@@ -60,7 +60,7 @@ export class BuddyList extends BuddyListConf {
populate(opts) { populate(opts) {
this.render_count = 0; this.render_count = 0;
this.container.html(""); this.$container.html("");
// We rely on our caller to give us items // We rely on our caller to give us items
// in already-sorted order. // in already-sorted order.
@@ -88,8 +88,8 @@ export class BuddyList extends BuddyListConf {
const html = this.items_to_html({ const html = this.items_to_html({
items, items,
}); });
this.container = $(this.container_sel); this.$container = $(this.container_sel);
this.container.append(html); this.$container.append(html);
// Invariant: more_keys.length >= items.length. // Invariant: more_keys.length >= items.length.
// (Usually they're the same, but occasionally keys // (Usually they're the same, but occasionally keys
@@ -102,8 +102,8 @@ export class BuddyList extends BuddyListConf {
} }
get_items() { get_items() {
const obj = this.container.find(`${this.item_sel}`); const $obj = this.$container.find(`${this.item_sel}`);
return obj.map((i, elem) => $(elem)); return $obj.map((i, elem) => $(elem));
} }
first_key() { first_key() {
@@ -141,8 +141,8 @@ export class BuddyList extends BuddyListConf {
if (pos < this.render_count) { if (pos < this.render_count) {
this.render_count -= 1; this.render_count -= 1;
const li = this.find_li({key: opts.key}); const $li = this.find_li({key: opts.key});
li.remove(); $li.remove();
this.update_padding(); this.update_padding();
} }
} }
@@ -182,18 +182,18 @@ export class BuddyList extends BuddyListConf {
const key = opts.key; const key = opts.key;
// Try direct DOM lookup first for speed. // Try direct DOM lookup first for speed.
let li = this.get_li_from_key({ let $li = this.get_li_from_key({
key, key,
}); });
if (li.length === 1) { if ($li.length === 1) {
return li; return $li;
} }
if (!opts.force_render) { if (!opts.force_render) {
// Most callers don't force us to render a list // Most callers don't force us to render a list
// item that wouldn't be on-screen anyway. // item that wouldn't be on-screen anyway.
return li; return $li;
} }
const pos = this.keys.indexOf(key); const pos = this.keys.indexOf(key);
@@ -208,11 +208,11 @@ export class BuddyList extends BuddyListConf {
pos, pos,
}); });
li = this.get_li_from_key({ $li = this.get_li_from_key({
key, key,
}); });
return li; return $li;
} }
insert_new_html(opts) { insert_new_html(opts) {
@@ -223,7 +223,7 @@ export class BuddyList extends BuddyListConf {
if (other_key === undefined) { if (other_key === undefined) {
if (pos === this.render_count) { if (pos === this.render_count) {
this.render_count += 1; this.render_count += 1;
this.container.append(html); this.$container.append(html);
this.update_padding(); this.update_padding();
} }
return; return;
@@ -231,8 +231,8 @@ export class BuddyList extends BuddyListConf {
if (pos < this.render_count) { if (pos < this.render_count) {
this.render_count += 1; this.render_count += 1;
const li = this.find_li({key: other_key}); const $li = this.find_li({key: other_key});
li.before(html); $li.before(html);
this.update_padding(); this.update_padding();
} }
} }
@@ -288,14 +288,14 @@ export class BuddyList extends BuddyListConf {
// This is a bit of a hack to make sure we at least have // This is a bit of a hack to make sure we at least have
// an empty list to start, before we get the initial payload. // an empty list to start, before we get the initial payload.
container = $(this.container_sel); $container = $(this.container_sel);
start_scroll_handler() { start_scroll_handler() {
// We have our caller explicitly call this to make // We have our caller explicitly call this to make
// sure everything's in place. // sure everything's in place.
const scroll_container = ui.get_scroll_element($(this.scroll_container_sel)); const $scroll_container = ui.get_scroll_element($(this.scroll_container_sel));
scroll_container.on("scroll", () => { $scroll_container.on("scroll", () => {
this.fill_screen_with_content(); this.fill_screen_with_content();
}); });
} }

View File

@@ -101,49 +101,49 @@ export function initialize() {
initialize_long_tap(); initialize_long_tap();
} }
function is_clickable_message_element(target) { function is_clickable_message_element($target) {
// This function defines all the elements within a message // This function defines all the elements within a message
// body that have UI behavior other than starting a reply. // body that have UI behavior other than starting a reply.
// Links should be handled by the browser. // Links should be handled by the browser.
if (target.closest("a").length > 0) { if ($target.closest("a").length > 0) {
return true; return true;
} }
// Forms for message editing contain input elements // Forms for message editing contain input elements
if (target.is("textarea") || target.is("input")) { if ($target.is("textarea") || $target.is("input")) {
return true; return true;
} }
// Widget for adjusting the height of a message. // Widget for adjusting the height of a message.
if (target.is("div.message_length_controller")) { if ($target.is("div.message_length_controller")) {
return true; return true;
} }
// Inline image and twitter previews. // Inline image and twitter previews.
if (target.is("img.message_inline_image") || target.is("img.twitter-avatar")) { if ($target.is("img.message_inline_image") || $target.is("img.twitter-avatar")) {
return true; return true;
} }
// UI elements for triggering message editing or viewing edit history. // UI elements for triggering message editing or viewing edit history.
if (target.is("i.edit_content_button") || target.is(".message_edit_notice")) { if ($target.is("i.edit_content_button") || $target.is(".message_edit_notice")) {
return true; return true;
} }
// For spoilers, allow clicking either the header or elements within it // For spoilers, allow clicking either the header or elements within it
if (target.is(".spoiler-header") || target.parents(".spoiler-header").length > 0) { if ($target.is(".spoiler-header") || $target.parents(".spoiler-header").length > 0) {
return true; return true;
} }
// Ideally, this should be done via ClipboardJS, but it doesn't support // Ideally, this should be done via ClipboardJS, but it doesn't support
// feature of stopPropagation once clicked. // feature of stopPropagation once clicked.
// See https://github.com/zenorocha/clipboard.js/pull/475 // See https://github.com/zenorocha/clipboard.js/pull/475
if (target.is(".copy_codeblock") || target.parents(".copy_codeblock").length > 0) { if ($target.is(".copy_codeblock") || $target.parents(".copy_codeblock").length > 0) {
return true; return true;
} }
// Don't select message on clicking message control buttons. // Don't select message on clicking message control buttons.
if (target.parents(".message_controls").length > 0) { if ($target.parents(".message_controls").length > 0) {
return true; return true;
} }
@@ -169,8 +169,8 @@ export function initialize() {
return; return;
} }
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
const id = rows.id(row); const id = rows.id($row);
if (message_edit.is_editing(id)) { if (message_edit.is_editing(id)) {
// Clicks on a message being edited shouldn't trigger a reply. // Clicks on a message being edited shouldn't trigger a reply.
@@ -261,45 +261,45 @@ export function initialize() {
// MESSAGE EDITING // MESSAGE EDITING
$("body").on("click", ".edit_content_button", function (e) { $("body").on("click", ".edit_content_button", function (e) {
const row = message_lists.current.get_row(rows.id($(this).closest(".message_row"))); const $row = message_lists.current.get_row(rows.id($(this).closest(".message_row")));
message_lists.current.select_id(rows.id(row)); message_lists.current.select_id(rows.id($row));
message_edit.start(row); message_edit.start($row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".always_visible_topic_edit,.on_hover_topic_edit", function (e) { $("body").on("click", ".always_visible_topic_edit,.on_hover_topic_edit", function (e) {
const recipient_row = $(this).closest(".recipient_row"); const $recipient_row = $(this).closest(".recipient_row");
message_edit.start_inline_topic_edit(recipient_row); message_edit.start_inline_topic_edit($recipient_row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".topic_edit_save", function (e) { $("body").on("click", ".topic_edit_save", function (e) {
const recipient_row = $(this).closest(".recipient_row"); const $recipient_row = $(this).closest(".recipient_row");
message_edit.save_inline_topic_edit(recipient_row); message_edit.save_inline_topic_edit($recipient_row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".topic_edit_cancel", function (e) { $("body").on("click", ".topic_edit_cancel", function (e) {
const recipient_row = $(this).closest(".recipient_row"); const $recipient_row = $(this).closest(".recipient_row");
message_edit.end_inline_topic_edit(recipient_row); message_edit.end_inline_topic_edit($recipient_row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".message_edit_save", function (e) { $("body").on("click", ".message_edit_save", function (e) {
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
message_edit.save_message_row_edit(row); message_edit.save_message_row_edit($row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".message_edit_cancel", function (e) { $("body").on("click", ".message_edit_cancel", function (e) {
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
message_edit.end_message_row_edit(row); message_edit.end_message_row_edit($row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
$("body").on("click", ".message_edit_close", function (e) { $("body").on("click", ".message_edit_close", function (e) {
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
message_edit.end_message_row_edit(row); message_edit.end_message_row_edit($row);
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
}); });
@@ -310,8 +310,8 @@ export function initialize() {
}); });
$(".message_edit_form .send-status-close").on("click", function () { $(".message_edit_form .send-status-close").on("click", function () {
const row_id = rows.id($(this).closest(".message_row")); const row_id = rows.id($(this).closest(".message_row"));
const send_status = $(`#message-edit-send-status-${CSS.escape(row_id)}`); const $send_status = $(`#message-edit-send-status-${CSS.escape(row_id)}`);
$(send_status).stop(true).fadeOut(200); $($send_status).stop(true).fadeOut(200);
}); });
$("body").on("click", ".message_edit_form .compose_upload_file", function (e) { $("body").on("click", ".message_edit_form .compose_upload_file", function (e) {
e.preventDefault(); e.preventDefault();
@@ -322,44 +322,44 @@ export function initialize() {
$("body").on("click", ".message_edit_form .markdown_preview", (e) => { $("body").on("click", ".message_edit_form .markdown_preview", (e) => {
e.preventDefault(); e.preventDefault();
const row = rows.get_closest_row(e.target); const $row = rows.get_closest_row(e.target);
const $msg_edit_content = row.find(".message_edit_content"); const $msg_edit_content = $row.find(".message_edit_content");
const content = $msg_edit_content.val(); const content = $msg_edit_content.val();
$msg_edit_content.hide(); $msg_edit_content.hide();
row.find(".markdown_preview").hide(); $row.find(".markdown_preview").hide();
row.find(".undo_markdown_preview").show(); $row.find(".undo_markdown_preview").show();
row.find(".preview_message_area").show(); $row.find(".preview_message_area").show();
compose.render_and_show_preview( compose.render_and_show_preview(
row.find(".markdown_preview_spinner"), $row.find(".markdown_preview_spinner"),
row.find(".preview_content"), $row.find(".preview_content"),
content, content,
); );
}); });
$("body").on("click", ".message_edit_form .undo_markdown_preview", (e) => { $("body").on("click", ".message_edit_form .undo_markdown_preview", (e) => {
e.preventDefault(); e.preventDefault();
const row = rows.get_closest_row(e.target); const $row = rows.get_closest_row(e.target);
row.find(".message_edit_content").show(); $row.find(".message_edit_content").show();
row.find(".undo_markdown_preview").hide(); $row.find(".undo_markdown_preview").hide();
row.find(".preview_message_area").hide(); $row.find(".preview_message_area").hide();
row.find(".preview_content").empty(); $row.find(".preview_content").empty();
row.find(".markdown_preview").show(); $row.find(".markdown_preview").show();
}); });
// RESOLVED TOPICS // RESOLVED TOPICS
$("body").on("click", ".message_header .on_hover_topic_resolve", (e) => { $("body").on("click", ".message_header .on_hover_topic_resolve", (e) => {
e.stopPropagation(); e.stopPropagation();
const recipient_row = $(e.target).closest(".recipient_row"); const $recipient_row = $(e.target).closest(".recipient_row");
const message_id = rows.id_for_recipient_row(recipient_row); const message_id = rows.id_for_recipient_row($recipient_row);
const topic_name = $(e.target).attr("data-topic-name"); const topic_name = $(e.target).attr("data-topic-name");
message_edit.toggle_resolve_topic(message_id, topic_name); message_edit.toggle_resolve_topic(message_id, topic_name);
}); });
$("body").on("click", ".message_header .on_hover_topic_unresolve", (e) => { $("body").on("click", ".message_header .on_hover_topic_unresolve", (e) => {
e.stopPropagation(); e.stopPropagation();
const recipient_row = $(e.target).closest(".recipient_row"); const $recipient_row = $(e.target).closest(".recipient_row");
const message_id = rows.id_for_recipient_row(recipient_row); const message_id = rows.id_for_recipient_row($recipient_row);
const topic_name = $(e.target).attr("data-topic-name"); const topic_name = $(e.target).attr("data-topic-name");
message_edit.toggle_resolve_topic(message_id, topic_name); message_edit.toggle_resolve_topic(message_id, topic_name);
}); });
@@ -449,9 +449,9 @@ export function initialize() {
e.stopPropagation(); e.stopPropagation();
// The element's parent may re-render while it is being passed to // The element's parent may re-render while it is being passed to
// other functions, so, we get topic_key first. // other functions, so, we get topic_key first.
const topic_row = $(e.target).closest("tr"); const $topic_row = $(e.target).closest("tr");
const topic_key = topic_row.attr("id").slice("recent_topics:".length - 1); const topic_key = $topic_row.attr("id").slice("recent_topics:".length - 1);
const topic_row_index = topic_row.index(); const topic_row_index = $topic_row.index();
recent_topics_ui.focus_clicked_element( recent_topics_ui.focus_clicked_element(
topic_row_index, topic_row_index,
recent_topics_ui.COLUMNS.topic, recent_topics_ui.COLUMNS.topic,
@@ -479,8 +479,8 @@ export function initialize() {
// RECIPIENT BARS // RECIPIENT BARS
function get_row_id_for_narrowing(narrow_link_elem) { function get_row_id_for_narrowing(narrow_link_elem) {
const group = rows.get_closest_group(narrow_link_elem); const $group = rows.get_closest_group(narrow_link_elem);
const msg_id = rows.id_for_recipient_row(group); const msg_id = rows.id_for_recipient_row($group);
const nearest = message_lists.current.get(msg_id); const nearest = message_lists.current.get(msg_id);
const selected = message_lists.current.selected_message(); const selected = message_lists.current.selected_message();
@@ -535,9 +535,9 @@ export function initialize() {
$("#user_presences") $("#user_presences")
.expectOne() .expectOne()
.on("click", ".selectable_sidebar_block", (e) => { .on("click", ".selectable_sidebar_block", (e) => {
const li = $(e.target).parents("li"); const $li = $(e.target).parents("li");
activity.narrow_for_user({li}); activity.narrow_for_user({$li});
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@@ -545,7 +545,7 @@ export function initialize() {
$(".tooltip").remove(); $(".tooltip").remove();
}); });
function do_render_buddy_list_tooltip(elem, title_data) { function do_render_buddy_list_tooltip($elem, title_data) {
let placement = "left"; let placement = "left";
let observer; let observer;
if (window.innerWidth < media_breakpoints_num.md) { if (window.innerWidth < media_breakpoints_num.md) {
@@ -553,7 +553,7 @@ export function initialize() {
// This will default to "bottom" placement for this tooltip. // This will default to "bottom" placement for this tooltip.
placement = "auto"; placement = "auto";
} }
tippy(elem[0], { tippy($elem[0], {
// Quickly display and hide right sidebar tooltips // Quickly display and hide right sidebar tooltips
// so that they don't stick and overlap with // so that they don't stick and overlap with
// each other. // each other.
@@ -598,22 +598,22 @@ export function initialize() {
// BUDDY LIST TOOLTIPS // BUDDY LIST TOOLTIPS
$("#user_presences").on("mouseenter", ".selectable_sidebar_block", (e) => { $("#user_presences").on("mouseenter", ".selectable_sidebar_block", (e) => {
e.stopPropagation(); e.stopPropagation();
const elem = $(e.currentTarget).closest(".user_sidebar_entry").find(".user-presence-link"); const $elem = $(e.currentTarget).closest(".user_sidebar_entry").find(".user-presence-link");
const user_id_string = elem.attr("data-user-id"); const user_id_string = $elem.attr("data-user-id");
const title_data = buddy_data.get_title_data(user_id_string, false); const title_data = buddy_data.get_title_data(user_id_string, false);
do_render_buddy_list_tooltip(elem.parent(), title_data); do_render_buddy_list_tooltip($elem.parent(), title_data);
}); });
// PM LIST TOOLTIPS // PM LIST TOOLTIPS
$("body").on("mouseenter", "#pm_user_status", (e) => { $("body").on("mouseenter", "#pm_user_status", (e) => {
e.stopPropagation(); e.stopPropagation();
const elem = $(e.currentTarget); const $elem = $(e.currentTarget);
const user_ids_string = elem.attr("data-user-ids-string"); const user_ids_string = $elem.attr("data-user-ids-string");
// This converts from 'true' in the DOM to true. // This converts from 'true' in the DOM to true.
const is_group = JSON.parse(elem.attr("data-is-group")); const is_group = JSON.parse($elem.attr("data-is-group"));
const title_data = buddy_data.get_title_data(user_ids_string, is_group); const title_data = buddy_data.get_title_data(user_ids_string, is_group);
do_render_buddy_list_tooltip(elem, title_data); do_render_buddy_list_tooltip($elem, title_data);
}); });
// MISC // MISC
@@ -791,7 +791,7 @@ export function initialize() {
overlays.open_overlay({ overlays.open_overlay({
name: overlay_name, name: overlay_name,
overlay: $(`#${CSS.escape(overlay_name)}`), $overlay: $(`#${CSS.escape(overlay_name)}`),
on_close: function () { on_close: function () {
// close popover // close popover
$(this).css({display: "block"}); $(this).css({display: "block"});

View File

@@ -32,16 +32,16 @@ export function phrase_match(query: string, phrase: string): boolean {
return false; return false;
} }
export function copy_data_attribute_value(elem: JQuery, key: string): void { export function copy_data_attribute_value($elem: JQuery, key: string): void {
// function to copy the value of data-key // function to copy the value of data-key
// attribute of the element to clipboard // attribute of the element to clipboard
const temp = $(document.createElement("input")); const $temp = $(document.createElement("input"));
$("body").append(temp); $("body").append($temp);
temp.val(elem.data(key)).trigger("select"); $temp.val($elem.data(key)).trigger("select");
document.execCommand("copy"); document.execCommand("copy");
temp.remove(); $temp.remove();
elem.fadeOut(250); $elem.fadeOut(250);
elem.fadeIn(1000); $elem.fadeIn(1000);
} }
export function has_mac_keyboard(): boolean { export function has_mac_keyboard(): boolean {
@@ -105,14 +105,14 @@ function toggle_password_visibility(
tippy_tooltips: boolean, tippy_tooltips: boolean,
): void { ): void {
let label; let label;
const password_field = $(password_field_id); const $password_field = $(password_field_id);
if (password_field.attr("type") === "password") { if ($password_field.attr("type") === "password") {
password_field.attr("type", "text"); $password_field.attr("type", "text");
$(password_selector).removeClass("fa-eye-slash").addClass("fa-eye"); $(password_selector).removeClass("fa-eye-slash").addClass("fa-eye");
label = $t({defaultMessage: "Hide password"}); label = $t({defaultMessage: "Hide password"});
} else { } else {
password_field.attr("type", "password"); $password_field.attr("type", "password");
$(password_selector).removeClass("fa-eye").addClass("fa-eye-slash"); $(password_selector).removeClass("fa-eye").addClass("fa-eye-slash");
label = $t({defaultMessage: "Show password"}); label = $t({defaultMessage: "Show password"});
} }

View File

@@ -32,16 +32,16 @@ export function toggle(opts: {
child_wants_focus?: boolean; child_wants_focus?: boolean;
selected?: number; selected?: number;
}): Toggle { }): Toggle {
const component = $("<div class='tab-switcher'></div>"); const $component = $("<div class='tab-switcher'></div>");
if (opts.html_class) { if (opts.html_class) {
// add a check inside passed arguments in case some extra // add a check inside passed arguments in case some extra
// classes need to be added for correct alignment or other purposes // classes need to be added for correct alignment or other purposes
component.addClass(opts.html_class); $component.addClass(opts.html_class);
} }
for (const [i, value] of opts.values.entries()) { for (const [i, value] of opts.values.entries()) {
// create a tab with a tab-id so they don't have to be referenced // create a tab with a tab-id so they don't have to be referenced
// by text value which can be inconsistent. // by text value which can be inconsistent.
const tab = $("<div>", { const $tab = $("<div>", {
class: "ind-tab", class: "ind-tab",
"data-tab-key": value.key, "data-tab-key": value.key,
"data-tab-id": i, "data-tab-id": i,
@@ -51,37 +51,37 @@ export function toggle(opts: {
/* istanbul ignore if */ /* istanbul ignore if */
if (value.label_html !== undefined) { if (value.label_html !== undefined) {
const html = value.label_html; const html = value.label_html;
tab.html(html); $tab.html(html);
} else { } else {
tab.text(value.label); $tab.text(value.label);
} }
// add proper classes for styling in CSS. // add proper classes for styling in CSS.
if (i === 0) { if (i === 0) {
// this should be default selected unless otherwise specified. // this should be default selected unless otherwise specified.
tab.addClass("first selected"); $tab.addClass("first selected");
} else if (i === opts.values.length - 1) { } else if (i === opts.values.length - 1) {
tab.addClass("last"); $tab.addClass("last");
} else { } else {
tab.addClass("middle"); $tab.addClass("middle");
} }
component.append(tab); $component.append($tab);
} }
const meta = { const meta = {
$ind_tab: component.find(".ind-tab"), $ind_tab: $component.find(".ind-tab"),
idx: -1, idx: -1,
}; };
// Returns false if the requested tab is disabled. // Returns false if the requested tab is disabled.
function select_tab(idx: number): boolean { function select_tab(idx: number): boolean {
const elem = meta.$ind_tab.eq(idx); const $elem = meta.$ind_tab.eq(idx);
if (elem.hasClass("disabled")) { if ($elem.hasClass("disabled")) {
return false; return false;
} }
meta.$ind_tab.removeClass("selected"); meta.$ind_tab.removeClass("selected");
elem.addClass("selected"); $elem.addClass("selected");
meta.idx = idx; meta.idx = idx;
if (opts.callback) { if (opts.callback) {
@@ -89,7 +89,7 @@ export function toggle(opts: {
} }
if (!opts.child_wants_focus) { if (!opts.child_wants_focus) {
elem.trigger("focus"); $elem.trigger("focus");
} }
return true; return true;
} }
@@ -124,7 +124,7 @@ export function toggle(opts: {
}); });
keydown_util.handle({ keydown_util.handle({
elem: meta.$ind_tab, $elem: meta.$ind_tab,
handlers: { handlers: {
ArrowLeft: maybe_go_left, ArrowLeft: maybe_go_left,
ArrowRight: maybe_go_right, ArrowRight: maybe_go_right,
@@ -172,7 +172,7 @@ export function toggle(opts: {
}, },
get() { get() {
return component; return $component;
}, },
// go through the process of finding the correct tab for a given name, // go through the process of finding the correct tab for a given name,
// and when found, select that one and provide the proper callback. // and when found, select that one and provide the proper callback.

View File

@@ -328,7 +328,7 @@ function insert_video_call_url(url, target_textarea) {
compose_ui.insert_syntax_and_focus(`[${link_text}](${url})`, target_textarea); compose_ui.insert_syntax_and_focus(`[${link_text}](${url})`, target_textarea);
} }
export function render_and_show_preview(preview_spinner, preview_content_box, content) { export function render_and_show_preview($preview_spinner, $preview_content_box, content) {
function show_preview(rendered_content, raw_content) { function show_preview(rendered_content, raw_content) {
// content is passed to check for status messages ("/me ...") // content is passed to check for status messages ("/me ...")
// and will be undefined in case of errors // and will be undefined in case of errors
@@ -344,16 +344,16 @@ export function render_and_show_preview(preview_spinner, preview_content_box, co
rendered_preview_html = rendered_content; rendered_preview_html = rendered_content;
} }
preview_content_box.html(util.clean_user_content_links(rendered_preview_html)); $preview_content_box.html(util.clean_user_content_links(rendered_preview_html));
rendered_markdown.update_elements(preview_content_box); rendered_markdown.update_elements($preview_content_box);
} }
if (content.length === 0) { if (content.length === 0) {
show_preview($t_html({defaultMessage: "Nothing to preview"})); show_preview($t_html({defaultMessage: "Nothing to preview"}));
} else { } else {
if (markdown.contains_backend_only_syntax(content)) { if (markdown.contains_backend_only_syntax(content)) {
const spinner = preview_spinner.expectOne(); const $spinner = $preview_spinner.expectOne();
loading.make_indicator(spinner); loading.make_indicator($spinner);
} else { } else {
// For messages that don't appear to contain syntax that // For messages that don't appear to contain syntax that
// is only supported by our backend Markdown processor, we // is only supported by our backend Markdown processor, we
@@ -374,13 +374,13 @@ export function render_and_show_preview(preview_spinner, preview_content_box, co
data: {content}, data: {content},
success(response_data) { success(response_data) {
if (markdown.contains_backend_only_syntax(content)) { if (markdown.contains_backend_only_syntax(content)) {
loading.destroy_indicator(preview_spinner); loading.destroy_indicator($preview_spinner);
} }
show_preview(response_data.rendered, content); show_preview(response_data.rendered, content);
}, },
error() { error() {
if (markdown.contains_backend_only_syntax(content)) { if (markdown.contains_backend_only_syntax(content)) {
loading.destroy_indicator(preview_spinner); loading.destroy_indicator($preview_spinner);
} }
show_preview($t_html({defaultMessage: "Failed to generate preview"})); show_preview($t_html({defaultMessage: "Failed to generate preview"}));
}, },
@@ -463,9 +463,9 @@ export function initialize() {
$("#compose_resolved_topic").on("click", ".compose_unresolve_topic", (event) => { $("#compose_resolved_topic").on("click", ".compose_unresolve_topic", (event) => {
event.preventDefault(); event.preventDefault();
const target = $(event.target).parents(".compose_resolved_topic"); const $target = $(event.target).parents(".compose_resolved_topic");
const stream_id = Number.parseInt(target.attr("data-stream-id"), 10); const stream_id = Number.parseInt($target.attr("data-stream-id"), 10);
const topic_name = target.attr("data-topic-name"); const topic_name = $target.attr("data-topic-name");
message_edit.with_first_message_id(stream_id, topic_name, (message_id) => { message_edit.with_first_message_id(stream_id, topic_name, (message_id) => {
message_edit.toggle_resolve_topic(message_id, topic_name); message_edit.toggle_resolve_topic(message_id, topic_name);
@@ -482,17 +482,17 @@ export function initialize() {
$("#compose_invite_users").on("click", ".compose_invite_link", (event) => { $("#compose_invite_users").on("click", ".compose_invite_link", (event) => {
event.preventDefault(); event.preventDefault();
const invite_row = $(event.target).parents(".compose_invite_user"); const $invite_row = $(event.target).parents(".compose_invite_user");
const user_id = Number.parseInt($(invite_row).data("user-id"), 10); const user_id = Number.parseInt($($invite_row).data("user-id"), 10);
const stream_id = Number.parseInt($(invite_row).data("stream-id"), 10); const stream_id = Number.parseInt($($invite_row).data("stream-id"), 10);
function success() { function success() {
const all_invites = $("#compose_invite_users"); const $all_invites = $("#compose_invite_users");
invite_row.remove(); $invite_row.remove();
if (all_invites.children().length === 0) { if ($all_invites.children().length === 0) {
all_invites.hide(); $all_invites.hide();
} }
} }
@@ -513,13 +513,13 @@ export function initialize() {
}); });
$("#compose_invite_users").on("click", ".compose_invite_close", (event) => { $("#compose_invite_users").on("click", ".compose_invite_close", (event) => {
const invite_row = $(event.target).parents(".compose_invite_user"); const $invite_row = $(event.target).parents(".compose_invite_user");
const all_invites = $("#compose_invite_users"); const $all_invites = $("#compose_invite_users");
invite_row.remove(); $invite_row.remove();
if (all_invites.children().length === 0) { if ($all_invites.children().length === 0) {
all_invites.hide(); $all_invites.hide();
} }
}); });
@@ -527,13 +527,13 @@ export function initialize() {
"click", "click",
".compose_private_stream_alert_close", ".compose_private_stream_alert_close",
(event) => { (event) => {
const stream_alert_row = $(event.target).parents(".compose_private_stream_alert"); const $stream_alert_row = $(event.target).parents(".compose_private_stream_alert");
const stream_alert = $("#compose_private_stream_alert"); const $stream_alert = $("#compose_private_stream_alert");
stream_alert_row.remove(); $stream_alert_row.remove();
if (stream_alert.children().length === 0) { if ($stream_alert.children().length === 0) {
stream_alert.hide(); $stream_alert.hide();
} }
}, },
); );
@@ -552,11 +552,11 @@ export function initialize() {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
let target_textarea; let $target_textarea;
let edit_message_id; let edit_message_id;
if ($(e.target).parents(".message_edit_form").length === 1) { if ($(e.target).parents(".message_edit_form").length === 1) {
edit_message_id = rows.id($(e.target).parents(".message_row")); edit_message_id = rows.id($(e.target).parents(".message_row"));
target_textarea = $(`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`); $target_textarea = $(`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`);
} }
let video_call_link; let video_call_link;
@@ -581,7 +581,7 @@ export function initialize() {
url: "/json/calls/zoom/create", url: "/json/calls/zoom/create",
success(res) { success(res) {
video_call_xhrs.delete(key); video_call_xhrs.delete(key);
insert_video_call_url(res.url, target_textarea); insert_video_call_url(res.url, $target_textarea);
}, },
error(xhr, status) { error(xhr, status) {
video_call_xhrs.delete(key); video_call_xhrs.delete(key);
@@ -619,13 +619,13 @@ export function initialize() {
channel.get({ channel.get({
url: "/json/calls/bigbluebutton/create", url: "/json/calls/bigbluebutton/create",
success(response) { success(response) {
insert_video_call_url(response.url, target_textarea); insert_video_call_url(response.url, $target_textarea);
}, },
}); });
} else { } else {
const video_call_id = util.random_int(100000000000000, 999999999999999); const video_call_id = util.random_int(100000000000000, 999999999999999);
video_call_link = page_params.jitsi_server_url + "/" + video_call_id; video_call_link = page_params.jitsi_server_url + "/" + video_call_id;
insert_video_call_url(video_call_link, target_textarea); insert_video_call_url(video_call_link, $target_textarea);
} }
}); });
@@ -635,20 +635,20 @@ export function initialize() {
$(e.target).toggleClass("has_popover"); $(e.target).toggleClass("has_popover");
let target_textarea; let $target_textarea;
let edit_message_id; let edit_message_id;
const compose_click_target = compose_ui.get_compose_click_target(e); const compose_click_target = compose_ui.get_compose_click_target(e);
if ($(compose_click_target).parents(".message_edit_form").length === 1) { if ($(compose_click_target).parents(".message_edit_form").length === 1) {
edit_message_id = rows.id($(compose_click_target).parents(".message_row")); edit_message_id = rows.id($(compose_click_target).parents(".message_row"));
target_textarea = $(`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`); $target_textarea = $(`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`);
} else { } else {
target_textarea = $(compose_click_target).closest("form").find("textarea"); $target_textarea = $(compose_click_target).closest("form").find("textarea");
} }
if ($(e.target).hasClass("has_popover")) { if ($(e.target).hasClass("has_popover")) {
const on_timestamp_selection = (val) => { const on_timestamp_selection = (val) => {
const timestr = `<time:${val}> `; const timestr = `<time:${val}> `;
compose_ui.insert_syntax_and_focus(timestr, target_textarea); compose_ui.insert_syntax_and_focus(timestr, $target_textarea);
}; };
flatpickr.show_flatpickr( flatpickr.show_flatpickr(
@@ -716,10 +716,10 @@ export function initialize() {
$("body").on("click", ".formatting_button", (e) => { $("body").on("click", ".formatting_button", (e) => {
const $compose_click_target = $(compose_ui.get_compose_click_target(e)); const $compose_click_target = $(compose_ui.get_compose_click_target(e));
const textarea = $compose_click_target.closest("form").find("textarea"); const $textarea = $compose_click_target.closest("form").find("textarea");
const format_type = $(e.target).attr("data-format-type"); const format_type = $(e.target).attr("data-format-type");
compose_ui.format_text(textarea, format_type); compose_ui.format_text($textarea, format_type);
textarea.trigger("focus"); $textarea.trigger("focus");
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
}); });

View File

@@ -72,8 +72,8 @@ export const _get_focus_area = get_focus_area;
export function set_focus(msg_type, opts) { export function set_focus(msg_type, opts) {
const focus_area = get_focus_area(msg_type, opts); const focus_area = get_focus_area(msg_type, opts);
if (window.getSelection().toString() === "" || opts.trigger !== "message click") { if (window.getSelection().toString() === "" || opts.trigger !== "message click") {
const elt = $(focus_area); const $elt = $(focus_area);
elt.trigger("focus").trigger("select"); $elt.trigger("focus").trigger("select");
} }
} }
@@ -156,9 +156,9 @@ export function maybe_scroll_up_selected_message() {
// scroll the compose box to avoid it. // scroll the compose box to avoid it.
return; return;
} }
const selected_row = message_lists.current.selected_row(); const $selected_row = message_lists.current.selected_row();
if (selected_row.height() > message_viewport.height() - 100) { if ($selected_row.height() > message_viewport.height() - 100) {
// For very tall messages whose height is close to the entire // For very tall messages whose height is close to the entire
// height of the viewport, don't auto-scroll the viewport to // height of the viewport, don't auto-scroll the viewport to
// the end of the message (since that makes it feel annoying // the end of the message (since that makes it feel annoying
@@ -166,7 +166,7 @@ export function maybe_scroll_up_selected_message() {
return; return;
} }
const cover = selected_row.offset().top + selected_row.height() - $("#compose").offset().top; const cover = $selected_row.offset().top + $selected_row.height() - $("#compose").offset().top;
if (cover > 0) { if (cover > 0) {
message_viewport.user_initiated_animate_scroll(cover + 20); message_viewport.user_initiated_animate_scroll(cover + 20);
} }
@@ -471,7 +471,7 @@ export function on_topic_narrow() {
} }
export function quote_and_reply(opts) { export function quote_and_reply(opts) {
const textarea = $("#compose-textarea"); const $textarea = $("#compose-textarea");
const message_id = message_lists.current.selected_id(); const message_id = message_lists.current.selected_id();
const message = message_lists.current.selected_message(); const message = message_lists.current.selected_message();
const quoting_placeholder = $t({defaultMessage: "[Quoting…]"}); const quoting_placeholder = $t({defaultMessage: "[Quoting…]"});
@@ -484,17 +484,17 @@ export function quote_and_reply(opts) {
// text, plus it's a complicated codepath that // text, plus it's a complicated codepath that
// can have other unintended consequences.) // can have other unintended consequences.)
if (textarea.caret() !== 0) { if ($textarea.caret() !== 0) {
// Insert a newline before quoted message if there is // Insert a newline before quoted message if there is
// already some content in the compose box and quoted // already some content in the compose box and quoted
// message is not being inserted at the beginning. // message is not being inserted at the beginning.
textarea.caret("\n"); $textarea.caret("\n");
} }
} else { } else {
respond_to_message(opts); respond_to_message(opts);
} }
compose_ui.insert_syntax_and_focus(quoting_placeholder + "\n", textarea); compose_ui.insert_syntax_and_focus(quoting_placeholder + "\n", $textarea);
function replace_content(message) { function replace_content(message) {
// Final message looks like: // Final message looks like:
@@ -502,7 +502,7 @@ export function quote_and_reply(opts) {
// ```quote // ```quote
// message content // message content
// ``` // ```
const prev_caret = textarea.caret(); const prev_caret = $textarea.caret();
let content = $t( let content = $t(
{defaultMessage: "{username} [said]({link_to_message}):"}, {defaultMessage: "{username} [said]({link_to_message}):"},
{ {
@@ -514,8 +514,8 @@ export function quote_and_reply(opts) {
const fence = fenced_code.get_unused_fence(message.raw_content); const fence = fenced_code.get_unused_fence(message.raw_content);
content += `${fence}quote\n${message.raw_content}\n${fence}`; content += `${fence}quote\n${message.raw_content}\n${fence}`;
const placeholder_offset = $(textarea).val().indexOf(quoting_placeholder); const placeholder_offset = $($textarea).val().indexOf(quoting_placeholder);
compose_ui.replace_syntax(quoting_placeholder, content, textarea); compose_ui.replace_syntax(quoting_placeholder, content, $textarea);
compose_ui.autosize_textarea($("#compose-textarea")); compose_ui.autosize_textarea($("#compose-textarea"));
// When replacing content in a textarea, we need to move the // When replacing content in a textarea, we need to move the
@@ -524,14 +524,14 @@ export function quote_and_reply(opts) {
// position. If we do, we need to move it by the increase in // position. If we do, we need to move it by the increase in
// the length of the content before the placeholder. // the length of the content before the placeholder.
if (prev_caret >= placeholder_offset + quoting_placeholder.length) { if (prev_caret >= placeholder_offset + quoting_placeholder.length) {
textarea.caret(prev_caret + content.length - quoting_placeholder.length); $textarea.caret(prev_caret + content.length - quoting_placeholder.length);
} else if (prev_caret > placeholder_offset) { } else if (prev_caret > placeholder_offset) {
/* In the rare case that our cursor was inside the /* In the rare case that our cursor was inside the
* placeholder, we treat that as though the cursor was * placeholder, we treat that as though the cursor was
* just after the placeholder. */ * just after the placeholder. */
textarea.caret(placeholder_offset + content.length + 1); $textarea.caret(placeholder_offset + content.length + 1);
} else { } else {
textarea.caret(prev_caret); $textarea.caret(prev_caret);
} }
} }

View File

@@ -2,7 +2,7 @@ import $ from "jquery";
import * as common from "./common"; import * as common from "./common";
export function show(error_html: string, bad_input?: JQuery, alert_class = "alert-error"): void { export function show(error_html: string, $bad_input?: JQuery, alert_class = "alert-error"): void {
$("#compose-send-status") $("#compose-send-status")
.removeClass(common.status_classes) .removeClass(common.status_classes)
.addClass(alert_class) .addClass(alert_class)
@@ -14,13 +14,13 @@ export function show(error_html: string, bad_input?: JQuery, alert_class = "aler
$("#compose-send-button span").show(); $("#compose-send-button span").show();
$("#compose-send-button").removeClass("disable-btn"); $("#compose-send-button").removeClass("disable-btn");
if (bad_input !== undefined) { if ($bad_input !== undefined) {
bad_input.trigger("focus").trigger("select"); $bad_input.trigger("focus").trigger("select");
} }
} }
export function show_not_subscribed(error_html: string, bad_input?: JQuery): void { export function show_not_subscribed(error_html: string, $bad_input?: JQuery): void {
show(error_html, bad_input, "home-error-bar"); show(error_html, $bad_input, "home-error-bar");
$(".compose-send-status-close").hide(); $(".compose-send-status-close").hide();
} }

View File

@@ -46,25 +46,25 @@ export function set_focused_recipient(msg_type) {
} }
function display_messages_normally() { function display_messages_normally() {
const table = rows.get_table(message_lists.current.table_name); const $table = rows.get_table(message_lists.current.table_name);
table.find(".recipient_row").removeClass("message-fade"); $table.find(".recipient_row").removeClass("message-fade");
normal_display = true; normal_display = true;
floating_recipient_bar.update(); floating_recipient_bar.update();
} }
function change_fade_state(elt, should_fade_group) { function change_fade_state($elt, should_fade_group) {
if (should_fade_group) { if (should_fade_group) {
elt.addClass("message-fade"); $elt.addClass("message-fade");
} else { } else {
elt.removeClass("message-fade"); $elt.removeClass("message-fade");
} }
} }
function fade_messages() { function fade_messages() {
let i; let i;
let first_message; let first_message;
let first_row; let $first_row;
let should_fade_group = false; let should_fade_group = false;
const visible_groups = message_viewport.visible_groups(false); const visible_groups = message_viewport.visible_groups(false);
@@ -72,8 +72,8 @@ function fade_messages() {
// Update the visible messages first, before the compose box opens // Update the visible messages first, before the compose box opens
for (i = 0; i < visible_groups.length; i += 1) { for (i = 0; i < visible_groups.length; i += 1) {
first_row = rows.first_message_in_group(visible_groups[i]); $first_row = rows.first_message_in_group(visible_groups[i]);
first_message = message_lists.current.get(rows.id(first_row)); first_message = message_lists.current.get(rows.id($first_row));
should_fade_group = compose_fade_helper.should_fade_message(first_message); should_fade_group = compose_fade_helper.should_fade_message(first_message);
change_fade_state($(visible_groups[i]), should_fade_group); change_fade_state($(visible_groups[i]), should_fade_group);
@@ -99,11 +99,11 @@ function fade_messages() {
// Note: The below algorithm relies on the fact that all_elts is // Note: The below algorithm relies on the fact that all_elts is
// sorted as it would be displayed in the message view // sorted as it would be displayed in the message view
for (i = 0; i < all_groups.length; i += 1) { for (i = 0; i < all_groups.length; i += 1) {
const group_elt = $(all_groups[i]); const $group_elt = $(all_groups[i]);
should_fade_group = compose_fade_helper.should_fade_message( should_fade_group = compose_fade_helper.should_fade_message(
rows.recipient_from_group(group_elt), rows.recipient_from_group($group_elt),
); );
change_fade_state(group_elt, should_fade_group); change_fade_state($group_elt, should_fade_group);
} }
floating_recipient_bar.update(); floating_recipient_bar.update();
@@ -115,14 +115,14 @@ function fade_messages() {
} }
const user_fade_config = { const user_fade_config = {
get_user_id(li) { get_user_id($li) {
return buddy_list.get_key_from_li({li}); return buddy_list.get_key_from_li({$li});
}, },
fade(li) { fade($li) {
return li.addClass("user-fade"); return $li.addClass("user-fade");
}, },
unfade(li) { unfade($li) {
return li.removeClass("user-fade"); return $li.removeClass("user-fade");
}, },
}; };
@@ -180,9 +180,9 @@ export function update_rendered_message_groups(message_groups, get_element) {
// important difference here is that we look at each message individually, whereas // important difference here is that we look at each message individually, whereas
// the other code takes advantage of blocks beneath recipient bars. // the other code takes advantage of blocks beneath recipient bars.
for (const message_group of message_groups) { for (const message_group of message_groups) {
const elt = get_element(message_group); const $elt = get_element(message_group);
const first_message = message_group.message_containers[0].msg; const first_message = message_group.message_containers[0].msg;
const should_fade = compose_fade_helper.should_fade_message(first_message); const should_fade = compose_fade_helper.should_fade_message(first_message);
change_fade_state(elt, should_fade); change_fade_state($elt, should_fade);
} }
} }

View File

@@ -13,10 +13,10 @@ const pill_config = {
}; };
export function initialize_pill() { export function initialize_pill() {
const container = $("#private_message_recipient").parent(); const $container = $("#private_message_recipient").parent();
const pill = input_pill.create({ const pill = input_pill.create({
container, $container,
pill_config, pill_config,
create_item_from_text: user_pill.create_item_from_email, create_item_from_text: user_pill.create_item_from_email,
get_text_from_item: user_pill.get_email_from_item, get_text_from_item: user_pill.get_email_from_item,

View File

@@ -19,14 +19,14 @@ export function composing() {
} }
function get_or_set(fieldname, keep_leading_whitespace) { function get_or_set(fieldname, keep_leading_whitespace) {
// We can't hoist the assignment of 'elem' out of this lambda, // We can't hoist the assignment of '$elem' out of this lambda,
// because the DOM element might not exist yet when get_or_set // because the DOM element might not exist yet when get_or_set
// is called. // is called.
return function (newval) { return function (newval) {
const elem = $(`#${CSS.escape(fieldname)}`); const $elem = $(`#${CSS.escape(fieldname)}`);
const oldval = elem.val(); const oldval = $elem.val();
if (newval !== undefined) { if (newval !== undefined) {
elem.val(newval); $elem.val(newval);
} }
return keep_leading_whitespace ? oldval.trimEnd() : oldval.trim(); return keep_leading_whitespace ? oldval.trimEnd() : oldval.trim();
}; };

View File

@@ -21,22 +21,22 @@ export function is_full_size() {
return full_size_status; return full_size_status;
} }
export function autosize_textarea(textarea) { export function autosize_textarea($textarea) {
// Since this supports both compose and file upload, one must pass // Since this supports both compose and file upload, one must pass
// in the text area to autosize. // in the text area to autosize.
if (!is_full_size()) { if (!is_full_size()) {
autosize.update(textarea); autosize.update($textarea);
} }
} }
export function smart_insert(textarea, syntax) { export function smart_insert($textarea, syntax) {
function is_space(c) { function is_space(c) {
return c === " " || c === "\t" || c === "\n"; return c === " " || c === "\t" || c === "\n";
} }
const pos = textarea.caret(); const pos = $textarea.caret();
const before_str = textarea.val().slice(0, pos); const before_str = $textarea.val().slice(0, pos);
const after_str = textarea.val().slice(pos); const after_str = $textarea.val().slice(pos);
if ( if (
pos > 0 && pos > 0 &&
@@ -60,32 +60,32 @@ export function smart_insert(textarea, syntax) {
syntax += " "; syntax += " ";
} }
textarea.trigger("focus"); $textarea.trigger("focus");
// We prefer to use insertText, which supports things like undo better // We prefer to use insertText, which supports things like undo better
// for rich-text editing features like inserting links. But we fall // for rich-text editing features like inserting links. But we fall
// back to textarea.caret if the browser doesn't support insertText. // back to textarea.caret if the browser doesn't support insertText.
if (!document.execCommand("insertText", false, syntax)) { if (!document.execCommand("insertText", false, syntax)) {
textarea.caret(syntax); $textarea.caret(syntax);
} }
autosize_textarea(textarea); autosize_textarea($textarea);
} }
export function insert_syntax_and_focus(syntax, textarea = $("#compose-textarea")) { export function insert_syntax_and_focus(syntax, $textarea = $("#compose-textarea")) {
// Generic helper for inserting syntax into the main compose box // Generic helper for inserting syntax into the main compose box
// where the cursor was and focusing the area. Mostly a thin // where the cursor was and focusing the area. Mostly a thin
// wrapper around smart_insert. // wrapper around smart_insert.
smart_insert(textarea, syntax); smart_insert($textarea, syntax);
} }
export function replace_syntax(old_syntax, new_syntax, textarea = $("#compose-textarea")) { export function replace_syntax(old_syntax, new_syntax, $textarea = $("#compose-textarea")) {
// Replaces `old_syntax` with `new_syntax` text in the compose box. Due to // Replaces `old_syntax` with `new_syntax` text in the compose box. Due to
// the way that JavaScript handles string replacements, if `old_syntax` is // the way that JavaScript handles string replacements, if `old_syntax` is
// a string it will only replace the first instance. If `old_syntax` is // a string it will only replace the first instance. If `old_syntax` is
// a RegExp with a global flag, it will replace all instances. // a RegExp with a global flag, it will replace all instances.
textarea.val( $textarea.val(
textarea.val().replace( $textarea.val().replace(
old_syntax, old_syntax,
() => () =>
// We need this anonymous function to avoid JavaScript's // We need this anonymous function to avoid JavaScript's
@@ -193,7 +193,7 @@ export function make_compose_box_original_size() {
$("#compose-textarea").trigger("focus"); $("#compose-textarea").trigger("focus");
} }
export function handle_keydown(event, textarea) { export function handle_keydown(event, $textarea) {
// The event.key property will have uppercase letter if // The event.key property will have uppercase letter if
// the "Shift + <key>" combo was used or the Caps Lock // the "Shift + <key>" combo was used or the Caps Lock
// key was on. We turn to key to lowercase so the key bindings // key was on. We turn to key to lowercase so the key bindings
@@ -212,26 +212,26 @@ export function handle_keydown(event, textarea) {
const isCmdOrCtrl = common.has_mac_keyboard() ? event.metaKey : event.ctrlKey; const isCmdOrCtrl = common.has_mac_keyboard() ? event.metaKey : event.ctrlKey;
if (type && isCmdOrCtrl) { if (type && isCmdOrCtrl) {
format_text(textarea, type); format_text($textarea, type);
autosize_textarea(textarea); autosize_textarea($textarea);
event.preventDefault(); event.preventDefault();
} }
} }
export function handle_keyup(event, textarea) { export function handle_keyup(event, $textarea) {
// Set the rtl class if the text has an rtl direction, remove it otherwise // Set the rtl class if the text has an rtl direction, remove it otherwise
rtl.set_rtl_class_for_textarea(textarea); rtl.set_rtl_class_for_textarea($textarea);
} }
export function format_text(textarea, type) { export function format_text($textarea, type) {
const italic_syntax = "*"; const italic_syntax = "*";
const bold_syntax = "**"; const bold_syntax = "**";
const bold_and_italic_syntax = "***"; const bold_and_italic_syntax = "***";
let is_selected_text_italic = false; let is_selected_text_italic = false;
let is_inner_text_italic = false; let is_inner_text_italic = false;
const field = textarea.get(0); const field = $textarea.get(0);
let range = textarea.range(); let range = $textarea.range();
let text = textarea.val(); let text = $textarea.val();
const selected_text = range.text; const selected_text = range.text;
// Remove new line and space around selected text. // Remove new line and space around selected text.
@@ -239,7 +239,7 @@ export function format_text(textarea, type) {
const right_trim_length = range.text.length - range.text.trimEnd().length; const right_trim_length = range.text.length - range.text.trimEnd().length;
field.setSelectionRange(range.start + left_trim_length, range.end - right_trim_length); field.setSelectionRange(range.start + left_trim_length, range.end - right_trim_length);
range = textarea.range(); range = $textarea.range();
const is_selection_bold = () => const is_selection_bold = () =>
// First check if there are enough characters before/after selection. // First check if there are enough characters before/after selection.

View File

@@ -106,12 +106,12 @@ export function warn_if_private_stream_is_linked(linked_stream) {
const stream_name = linked_stream.name; const stream_name = linked_stream.name;
const warning_area = $("#compose_private_stream_alert"); const $warning_area = $("#compose_private_stream_alert");
const context = {stream_name}; const context = {stream_name};
const new_row = render_compose_private_stream_alert(context); const new_row = render_compose_private_stream_alert(context);
warning_area.append(new_row); $warning_area.append(new_row);
warning_area.show(); $warning_area.show();
} }
export function warn_if_mentioning_unsubscribed_user(mentioned) { export function warn_if_mentioning_unsubscribed_user(mentioned) {
@@ -143,10 +143,10 @@ export function warn_if_mentioning_unsubscribed_user(mentioned) {
} }
if (needs_subscribe_warning(user_id, sub.stream_id)) { if (needs_subscribe_warning(user_id, sub.stream_id)) {
const error_area = $("#compose_invite_users"); const $error_area = $("#compose_invite_users");
const existing_invites_area = $("#compose_invite_users .compose_invite_user"); const $existing_invites_area = $("#compose_invite_users .compose_invite_user");
const existing_invites = Array.from($(existing_invites_area), (user_row) => const existing_invites = Array.from($($existing_invites_area), (user_row) =>
Number.parseInt($(user_row).data("user-id"), 10), Number.parseInt($(user_row).data("user-id"), 10),
); );
@@ -159,10 +159,10 @@ export function warn_if_mentioning_unsubscribed_user(mentioned) {
}; };
const new_row = render_compose_invite_users(context); const new_row = render_compose_invite_users(context);
error_area.append(new_row); $error_area.append(new_row);
} }
error_area.show(); $error_area.show();
} }
} }
@@ -224,14 +224,14 @@ function show_all_everyone_warnings(stream_id) {
count: stream_count, count: stream_count,
mention: wildcard_mention, mention: wildcard_mention,
}); });
const error_area_all_everyone = $("#compose-all-everyone"); const $error_area_all_everyone = $("#compose-all-everyone");
// only show one error for any number of @all or @everyone mentions // only show one error for any number of @all or @everyone mentions
if (!error_area_all_everyone.is(":visible")) { if (!$error_area_all_everyone.is(":visible")) {
error_area_all_everyone.append(all_everyone_template); $error_area_all_everyone.append(all_everyone_template);
} }
error_area_all_everyone.show(); $error_area_all_everyone.show();
user_acknowledged_all_everyone = false; user_acknowledged_all_everyone = false;
} }
@@ -245,13 +245,13 @@ function show_announce_warnings(stream_id) {
const stream_count = peer_data.get_subscriber_count(stream_id) || 0; const stream_count = peer_data.get_subscriber_count(stream_id) || 0;
const announce_template = render_compose_announce({count: stream_count}); const announce_template = render_compose_announce({count: stream_count});
const error_area_announce = $("#compose-announce"); const $error_area_announce = $("#compose-announce");
if (!error_area_announce.is(":visible")) { if (!$error_area_announce.is(":visible")) {
error_area_announce.append(announce_template); $error_area_announce.append(announce_template);
} }
error_area_announce.show(); $error_area_announce.show();
user_acknowledged_announce = false; user_acknowledged_announce = false;
} }
@@ -660,12 +660,12 @@ export function check_overflow_text() {
// expensive. // expensive.
const text = compose_state.message_content(); const text = compose_state.message_content();
const max_length = page_params.max_message_length; const max_length = page_params.max_message_length;
const indicator = $("#compose_limit_indicator"); const $indicator = $("#compose_limit_indicator");
if (text.length > max_length) { if (text.length > max_length) {
indicator.addClass("over_limit"); $indicator.addClass("over_limit");
$("#compose-textarea").addClass("over_limit"); $("#compose-textarea").addClass("over_limit");
indicator.text(text.length + "/" + max_length); $indicator.text(text.length + "/" + max_length);
compose_error.show( compose_error.show(
$t_html( $t_html(
{ {
@@ -677,16 +677,16 @@ export function check_overflow_text() {
); );
$("#compose-send-button").prop("disabled", true); $("#compose-send-button").prop("disabled", true);
} else if (text.length > 0.9 * max_length) { } else if (text.length > 0.9 * max_length) {
indicator.removeClass("over_limit"); $indicator.removeClass("over_limit");
$("#compose-textarea").removeClass("over_limit"); $("#compose-textarea").removeClass("over_limit");
indicator.text(text.length + "/" + max_length); $indicator.text(text.length + "/" + max_length);
$("#compose-send-button").prop("disabled", false); $("#compose-send-button").prop("disabled", false);
if ($("#compose-send-status").hasClass("alert-error")) { if ($("#compose-send-status").hasClass("alert-error")) {
$("#compose-send-status").stop(true).fadeOut(); $("#compose-send-status").stop(true).fadeOut();
} }
} else { } else {
indicator.text(""); $indicator.text("");
$("#compose-textarea").removeClass("over_limit"); $("#compose-textarea").removeClass("over_limit");
$("#compose-send-button").prop("disabled", false); $("#compose-send-button").prop("disabled", false);

View File

@@ -153,7 +153,7 @@ export function should_enter_send(e) {
return this_enter_sends; return this_enter_sends;
} }
export function handle_enter(textarea, e) { export function handle_enter($textarea, e) {
// Used only if Enter doesn't send. // Used only if Enter doesn't send.
// Since this Enter doesn't send, we just want to do // Since this Enter doesn't send, we just want to do
@@ -175,15 +175,15 @@ export function handle_enter(textarea, e) {
// To properly emulate browser "Enter", if the // To properly emulate browser "Enter", if the
// user had selected something in the textarea, // user had selected something in the textarea,
// we need those characters to be cleared. // we need those characters to be cleared.
const range = textarea.range(); const range = $textarea.range();
if (range.length > 0) { if (range.length > 0) {
textarea.range(range.start, range.end).range(""); $textarea.range(range.start, range.end).range("");
} }
// Now add the newline, remembering to resize the // Now add the newline, remembering to resize the
// textarea if needed. // textarea if needed.
textarea.caret("\n"); $textarea.caret("\n");
compose_ui.autosize_textarea(textarea); compose_ui.autosize_textarea($textarea);
e.preventDefault(); e.preventDefault();
} }
@@ -191,7 +191,7 @@ export function handle_enter(textarea, e) {
// We can't focus at the time of keydown because we need to wait for typeahead. // We can't focus at the time of keydown because we need to wait for typeahead.
// And we can't compute where to focus at the time of keyup because only the keydown // And we can't compute where to focus at the time of keyup because only the keydown
// has reliable information about whether it was a Tab or a Shift+Tab. // has reliable information about whether it was a Tab or a Shift+Tab.
let nextFocus = false; let $nextFocus = false;
function handle_keydown(e) { function handle_keydown(e) {
const key = e.key; const key = e.key;
@@ -245,11 +245,11 @@ function handle_keydown(e) {
} else if (on_stream || on_topic || on_pm) { } else if (on_stream || on_topic || on_pm) {
// We are doing the focusing on keyup to not abort the typeahead. // We are doing the focusing on keyup to not abort the typeahead.
if (on_stream) { if (on_stream) {
nextFocus = $("#stream_message_recipient_topic"); $nextFocus = $("#stream_message_recipient_topic");
} else if (on_topic) { } else if (on_topic) {
nextFocus = $("#compose-textarea"); $nextFocus = $("#compose-textarea");
} else if (on_pm) { } else if (on_pm) {
nextFocus = $("#compose-textarea"); $nextFocus = $("#compose-textarea");
} }
} }
} }
@@ -259,18 +259,18 @@ function handle_keyup(e) {
if ( if (
// Enter key or Tab key // Enter key or Tab key
(e.key === "Enter" || (e.key === "Tab" && !e.shiftKey)) && (e.key === "Enter" || (e.key === "Tab" && !e.shiftKey)) &&
nextFocus $nextFocus
) { ) {
nextFocus.trigger("focus"); $nextFocus.trigger("focus");
nextFocus = false; $nextFocus = false;
// Prevent the form from submitting // Prevent the form from submitting
e.preventDefault(); e.preventDefault();
} }
} }
export function split_at_cursor(query, input) { export function split_at_cursor(query, $input) {
const cursor = input.caret(); const cursor = $input.caret();
return [query.slice(0, cursor), query.slice(cursor)]; return [query.slice(0, cursor), query.slice(cursor)];
} }
@@ -517,10 +517,10 @@ export function get_person_suggestions(query, opts) {
export function get_stream_topic_data(hacky_this) { export function get_stream_topic_data(hacky_this) {
const opts = {}; const opts = {};
const message_row = hacky_this.$element.closest(".message_row"); const $message_row = hacky_this.$element.closest(".message_row");
if (message_row.length === 1) { if ($message_row.length === 1) {
// we are editing a message so we try to use it's keys. // we are editing a message so we try to use it's keys.
const msg = message_store.get(rows.id(message_row)); const msg = message_store.get(rows.id($message_row));
if (msg.type === "stream") { if (msg.type === "stream") {
opts.stream = msg.stream; opts.stream = msg.stream;
opts.topic = msg.topic; opts.topic = msg.topic;
@@ -770,7 +770,7 @@ export function content_typeahead_selected(item, event) {
const pieces = split_at_cursor(this.query, this.$element); const pieces = split_at_cursor(this.query, this.$element);
let beginning = pieces[0]; let beginning = pieces[0];
let rest = pieces[1]; let rest = pieces[1];
const textbox = this.$element; const $textbox = this.$element;
// this highlight object will hold the start and end indices // this highlight object will hold the start and end indices
// for highlighting any placeholder text // for highlighting any placeholder text
const highlight = {}; const highlight = {};
@@ -898,9 +898,9 @@ export function content_typeahead_selected(item, event) {
if (rest.startsWith(">")) { if (rest.startsWith(">")) {
rest = rest.slice(1); rest = rest.slice(1);
} }
textbox.val(beginning + rest); $textbox.val(beginning + rest);
textbox.caret(beginning.length, beginning.length); $textbox.caret(beginning.length, beginning.length);
compose_ui.autosize_textarea(textbox); compose_ui.autosize_textarea($textbox);
}; };
flatpickr.show_flatpickr(this.$element[0], on_timestamp_selection, timestamp); flatpickr.show_flatpickr(this.$element[0], on_timestamp_selection, timestamp);
return beginning + rest; return beginning + rest;
@@ -908,19 +908,19 @@ export function content_typeahead_selected(item, event) {
} }
// Keep the cursor after the newly inserted text / selecting the // Keep the cursor after the newly inserted text / selecting the
// placeholder text, as Bootstrap will call textbox.change() to // placeholder text, as Bootstrap will call $textbox.change() to
// overwrite the text in the textbox. // overwrite the text in the textbox.
setTimeout(() => { setTimeout(() => {
if (item.placeholder) { if (item.placeholder) {
// This placeholder block is exclusively for slash // This placeholder block is exclusively for slash
// commands, which always appear at the start of the message. // commands, which always appear at the start of the message.
textbox.get(0).setSelectionRange(highlight.start, highlight.end); $textbox.get(0).setSelectionRange(highlight.start, highlight.end);
textbox.trigger("focus"); $textbox.trigger("focus");
} else { } else {
textbox.caret(beginning.length, beginning.length); $textbox.caret(beginning.length, beginning.length);
} }
// Also, trigger autosize to check if compose box needs to be resized. // Also, trigger autosize to check if compose box needs to be resized.
compose_ui.autosize_textarea(textbox); compose_ui.autosize_textarea($textbox);
}, 0); }, 0);
return beginning + rest; return beginning + rest;
} }

View File

@@ -20,67 +20,67 @@ This library implements two related, similar concepts:
const _message_content_height_cache = new Map(); const _message_content_height_cache = new Map();
function show_more_link(row) { function show_more_link($row) {
row.find(".message_condenser").hide(); $row.find(".message_condenser").hide();
row.find(".message_expander").show(); $row.find(".message_expander").show();
} }
function show_condense_link(row) { function show_condense_link($row) {
row.find(".message_expander").hide(); $row.find(".message_expander").hide();
row.find(".message_condenser").show(); $row.find(".message_condenser").show();
} }
function condense_row(row) { function condense_row($row) {
const content = row.find(".message_content"); const $content = $row.find(".message_content");
content.addClass("condensed"); $content.addClass("condensed");
show_more_link(row); show_more_link($row);
} }
function uncondense_row(row) { function uncondense_row($row) {
const content = row.find(".message_content"); const $content = $row.find(".message_content");
content.removeClass("condensed"); $content.removeClass("condensed");
show_condense_link(row); show_condense_link($row);
} }
export function uncollapse(row) { export function uncollapse($row) {
// Uncollapse a message, restoring the condensed message [More] or // Uncollapse a message, restoring the condensed message [More] or
// [Show less] link if necessary. // [Show less] link if necessary.
const message = message_lists.current.get(rows.id(row)); const message = message_lists.current.get(rows.id($row));
message.collapsed = false; message.collapsed = false;
message_flags.save_uncollapsed(message); message_flags.save_uncollapsed(message);
const process_row = function process_row(row) { const process_row = function process_row($row) {
const content = row.find(".message_content"); const $content = $row.find(".message_content");
content.removeClass("collapsed"); $content.removeClass("collapsed");
if (message.condensed === true) { if (message.condensed === true) {
// This message was condensed by the user, so re-show the // This message was condensed by the user, so re-show the
// [More] link. // [More] link.
condense_row(row); condense_row($row);
} else if (message.condensed === false) { } else if (message.condensed === false) {
// This message was un-condensed by the user, so re-show the // This message was un-condensed by the user, so re-show the
// [Show less] link. // [Show less] link.
uncondense_row(row); uncondense_row($row);
} else if (content.hasClass("could-be-condensed")) { } else if ($content.hasClass("could-be-condensed")) {
// By default, condense a long message. // By default, condense a long message.
condense_row(row); condense_row($row);
} else { } else {
// This was a short message, no more need for a [More] link. // This was a short message, no more need for a [More] link.
row.find(".message_expander").hide(); $row.find(".message_expander").hide();
} }
}; };
// We also need to collapse this message in the home view // We also need to collapse this message in the home view
const home_row = message_lists.home.get_row(rows.id(row)); const $home_row = message_lists.home.get_row(rows.id($row));
process_row(row); process_row($row);
process_row(home_row); process_row($home_row);
} }
export function collapse(row) { export function collapse($row) {
// Collapse a message, hiding the condensed message [More] or // Collapse a message, hiding the condensed message [More] or
// [Show less] link if necessary. // [Show less] link if necessary.
const message = message_lists.current.get(rows.id(row)); const message = message_lists.current.get(rows.id($row));
message.collapsed = true; message.collapsed = true;
if (message.locally_echoed) { if (message.locally_echoed) {
@@ -93,16 +93,16 @@ export function collapse(row) {
message_flags.save_collapsed(message); message_flags.save_collapsed(message);
const process_row = function process_row(row) { const process_row = function process_row($row) {
row.find(".message_content").addClass("collapsed"); $row.find(".message_content").addClass("collapsed");
show_more_link(row); show_more_link($row);
}; };
// We also need to collapse this message in the home view // We also need to collapse this message in the home view
const home_row = message_lists.home.get_row(rows.id(row)); const $home_row = message_lists.home.get_row(rows.id($row));
process_row(row); process_row($row);
process_row(home_row); process_row($home_row);
} }
export function toggle_collapse(message) { export function toggle_collapse(message) {
@@ -121,30 +121,30 @@ export function toggle_collapse(message) {
// * If the message is fully visible, either because it's too short to // * If the message is fully visible, either because it's too short to
// condense or because it's already uncondensed, collapse it // condense or because it's already uncondensed, collapse it
const row = message_lists.current.get_row(message.id); const $row = message_lists.current.get_row(message.id);
if (!row) { if (!$row) {
return; return;
} }
const content = row.find(".message_content"); const $content = $row.find(".message_content");
const is_condensable = content.hasClass("could-be-condensed"); const is_condensable = $content.hasClass("could-be-condensed");
const is_condensed = content.hasClass("condensed"); const is_condensed = $content.hasClass("condensed");
if (message.collapsed) { if (message.collapsed) {
if (is_condensable) { if (is_condensable) {
message.condensed = true; message.condensed = true;
content.addClass("condensed"); $content.addClass("condensed");
show_message_expander(row); show_message_expander($row);
row.find(".message_condenser").hide(); $row.find(".message_condenser").hide();
} }
uncollapse(row); uncollapse($row);
} else { } else {
if (is_condensed) { if (is_condensed) {
message.condensed = false; message.condensed = false;
content.removeClass("condensed"); $content.removeClass("condensed");
hide_message_expander(row); hide_message_expander($row);
row.find(".message_condenser").show(); $row.find(".message_condenser").show();
} else { } else {
collapse(row); collapse($row);
} }
} }
} }
@@ -170,27 +170,27 @@ function get_message_height(elem, message_id) {
return height; return height;
} }
export function hide_message_expander(row) { export function hide_message_expander($row) {
if (row.find(".could-be-condensed").length !== 0) { if ($row.find(".could-be-condensed").length !== 0) {
row.find(".message_expander").hide(); $row.find(".message_expander").hide();
} }
} }
export function hide_message_condenser(row) { export function hide_message_condenser($row) {
if (row.find(".could-be-condensed").length !== 0) { if ($row.find(".could-be-condensed").length !== 0) {
row.find(".message_condenser").hide(); $row.find(".message_condenser").hide();
} }
} }
export function show_message_expander(row) { export function show_message_expander($row) {
if (row.find(".could-be-condensed").length !== 0) { if ($row.find(".could-be-condensed").length !== 0) {
row.find(".message_expander").show(); $row.find(".message_expander").show();
} }
} }
export function show_message_condenser(row) { export function show_message_condenser($row) {
if (row.find(".could-be-condensed").length !== 0) { if ($row.find(".could-be-condensed").length !== 0) {
row.find(".message_condenser").show(); $row.find(".message_condenser").show();
} }
} }
@@ -198,9 +198,9 @@ export function condense_and_collapse(elems) {
const height_cutoff = message_viewport.height() * 0.65; const height_cutoff = message_viewport.height() * 0.65;
for (const elem of elems) { for (const elem of elems) {
const content = $(elem).find(".message_content"); const $content = $(elem).find(".message_content");
if (content.length !== 1) { if ($content.length !== 1) {
// We could have a "/me did this" message or something // We could have a "/me did this" message or something
// else without a `message_content` div. // else without a `message_content` div.
continue; continue;
@@ -221,9 +221,9 @@ export function condense_and_collapse(elems) {
const long_message = message_height > height_cutoff; const long_message = message_height > height_cutoff;
if (long_message) { if (long_message) {
// All long messages are flagged as such. // All long messages are flagged as such.
content.addClass("could-be-condensed"); $content.addClass("could-be-condensed");
} else { } else {
content.removeClass("could-be-condensed"); $content.removeClass("could-be-condensed");
} }
// If message.condensed is defined, then the user has manually // If message.condensed is defined, then the user has manually
@@ -242,14 +242,14 @@ export function condense_and_collapse(elems) {
// By default, condense a long message. // By default, condense a long message.
condense_row($(elem)); condense_row($(elem));
} else { } else {
content.removeClass("condensed"); $content.removeClass("condensed");
$(elem).find(".message_expander").hide(); $(elem).find(".message_expander").hide();
} }
// Completely hide the message and replace it with a [More] // Completely hide the message and replace it with a [More]
// link if the user has collapsed it. // link if the user has collapsed it.
if (message.collapsed) { if (message.collapsed) {
content.addClass("collapsed"); $content.addClass("collapsed");
$(elem).find(".message_expander").show(); $(elem).find(".message_expander").show();
} }
} }
@@ -259,27 +259,27 @@ export function initialize() {
$("#message_feed_container").on("click", ".message_expander", function (e) { $("#message_feed_container").on("click", ".message_expander", function (e) {
// Expanding a message can mean either uncollapsing or // Expanding a message can mean either uncollapsing or
// uncondensing it. // uncondensing it.
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
const message = message_lists.current.get(rows.id(row)); const message = message_lists.current.get(rows.id($row));
const content = row.find(".message_content"); const $content = $row.find(".message_content");
if (message.collapsed) { if (message.collapsed) {
// Uncollapse. // Uncollapse.
uncollapse(row); uncollapse($row);
} else if (content.hasClass("condensed")) { } else if ($content.hasClass("condensed")) {
// Uncondense (show the full long message). // Uncondense (show the full long message).
message.condensed = false; message.condensed = false;
content.removeClass("condensed"); $content.removeClass("condensed");
$(this).hide(); $(this).hide();
row.find(".message_condenser").show(); $row.find(".message_condenser").show();
} }
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
}); });
$("#message_feed_container").on("click", ".message_condenser", function (e) { $("#message_feed_container").on("click", ".message_condenser", function (e) {
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
message_lists.current.get(rows.id(row)).condensed = true; message_lists.current.get(rows.id($row)).condensed = true;
condense_row(row); condense_row($row);
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
}); });

View File

@@ -6,15 +6,15 @@ import * as message_lists from "./message_lists";
import {page_params} from "./page_params"; import {page_params} from "./page_params";
import * as rows from "./rows"; import * as rows from "./rows";
function find_boundary_tr(initial_tr, iterate_row) { function find_boundary_tr($initial_tr, iterate_row) {
let j; let j;
let skip_same_td_check = false; let skip_same_td_check = false;
let tr = initial_tr; let $tr = $initial_tr;
// If the selection boundary is somewhere that does not have a // If the selection boundary is somewhere that does not have a
// parent tr, we should let the browser handle the copy-paste // parent tr, we should let the browser handle the copy-paste
// entirely on its own // entirely on its own
if (tr.length === 0) { if ($tr.length === 0) {
return undefined; return undefined;
} }
@@ -24,8 +24,8 @@ function find_boundary_tr(initial_tr, iterate_row) {
// To ensure we can't enter an infinite loop, bail out (and let the // To ensure we can't enter an infinite loop, bail out (and let the
// browser handle the copy-paste on its own) if we don't hit what we // browser handle the copy-paste on its own) if we don't hit what we
// are looking for within 10 rows. // are looking for within 10 rows.
for (j = 0; !tr.is(".message_row") && j < 10; j += 1) { for (j = 0; !$tr.is(".message_row") && j < 10; j += 1) {
tr = iterate_row(tr); $tr = iterate_row($tr);
} }
if (j === 10) { if (j === 10) {
return undefined; return undefined;
@@ -36,12 +36,12 @@ function find_boundary_tr(initial_tr, iterate_row) {
// in this case) // in this case)
skip_same_td_check = true; skip_same_td_check = true;
} }
return [rows.id(tr), skip_same_td_check]; return [rows.id($tr), skip_same_td_check];
} }
function construct_recipient_header(message_row) { function construct_recipient_header($message_row) {
const message_header_content = rows const message_header_content = rows
.get_message_recipient_header(message_row) .get_message_recipient_header($message_row)
.text() .text()
.replace(/\s+/g, " ") .replace(/\s+/g, " ")
.replace(/^\s/, "") .replace(/^\s/, "")
@@ -64,40 +64,40 @@ Do not be afraid to change this code if you understand
how modern browsers deal with copy/paste. Just test how modern browsers deal with copy/paste. Just test
your changes carefully. your changes carefully.
*/ */
function construct_copy_div(div, start_id, end_id) { function construct_copy_div($div, start_id, end_id) {
const copy_rows = rows.visible_range(start_id, end_id); const copy_rows = rows.visible_range(start_id, end_id);
const start_row = copy_rows[0]; const $start_row = copy_rows[0];
const start_recipient_row = rows.get_message_recipient_row(start_row); const $start_recipient_row = rows.get_message_recipient_row($start_row);
const start_recipient_row_id = rows.id_for_recipient_row(start_recipient_row); const start_recipient_row_id = rows.id_for_recipient_row($start_recipient_row);
let should_include_start_recipient_header = false; let should_include_start_recipient_header = false;
let last_recipient_row_id = start_recipient_row_id; let last_recipient_row_id = start_recipient_row_id;
for (const row of copy_rows) { for (const $row of copy_rows) {
const recipient_row_id = rows.id_for_recipient_row(rows.get_message_recipient_row(row)); const recipient_row_id = rows.id_for_recipient_row(rows.get_message_recipient_row($row));
// if we found a message from another recipient, // if we found a message from another recipient,
// it means that we have messages from several recipients, // it means that we have messages from several recipients,
// so we have to add new recipient's bar to final copied message // so we have to add new recipient's bar to final copied message
// and wouldn't forget to add start_recipient's bar at the beginning of final message // and wouldn't forget to add start_recipient's bar at the beginning of final message
if (recipient_row_id !== last_recipient_row_id) { if (recipient_row_id !== last_recipient_row_id) {
div.append(construct_recipient_header(row)); $div.append(construct_recipient_header($row));
last_recipient_row_id = recipient_row_id; last_recipient_row_id = recipient_row_id;
should_include_start_recipient_header = true; should_include_start_recipient_header = true;
} }
const message = message_lists.current.get(rows.id(row)); const message = message_lists.current.get(rows.id($row));
const message_firstp = $(message.content).slice(0, 1); const $message_firstp = $(message.content).slice(0, 1);
message_firstp.prepend(message.sender_full_name + ": "); $message_firstp.prepend(message.sender_full_name + ": ");
div.append(message_firstp); $div.append($message_firstp);
div.append($(message.content).slice(1)); $div.append($(message.content).slice(1));
} }
if (should_include_start_recipient_header) { if (should_include_start_recipient_header) {
div.prepend(construct_recipient_header(start_row)); $div.prepend(construct_recipient_header($start_row));
} }
} }
function select_div(div, selection) { function select_div($div, selection) {
div.css({ $div.css({
position: "absolute", position: "absolute",
left: "-99999px", left: "-99999px",
// Color and background is made according to "light theme" // Color and background is made according to "light theme"
@@ -110,8 +110,8 @@ function select_div(div, selection) {
color: "#333", color: "#333",
background: "#FFF", background: "#FFF",
}).attr("id", "copytempdiv"); }).attr("id", "copytempdiv");
$("body").append(div); $("body").append($div);
selection.selectAllChildren(div[0]); selection.selectAllChildren($div[0]);
} }
function remove_div(div, ranges, selection) { function remove_div(div, ranges, selection) {
@@ -149,7 +149,7 @@ export function copy_handler() {
const start_id = analysis.start_id; const start_id = analysis.start_id;
const end_id = analysis.end_id; const end_id = analysis.end_id;
const skip_same_td_check = analysis.skip_same_td_check; const skip_same_td_check = analysis.skip_same_td_check;
const div = $("<div>"); const $div = $("<div>");
if (start_id === undefined || end_id === undefined) { if (start_id === undefined || end_id === undefined) {
// In this case either the starting message or the ending // In this case either the starting message or the ending
@@ -176,13 +176,13 @@ export function copy_handler() {
// chance for overlaps between same message ids, avoiding which is much // chance for overlaps between same message ids, avoiding which is much
// more difficult since we can get a range (start_id and end_id) for // more difficult since we can get a range (start_id and end_id) for
// each selection `Range`. // each selection `Range`.
construct_copy_div(div, start_id, end_id); construct_copy_div($div, start_id, end_id);
// Select div so that the browser will copy it // Select div so that the browser will copy it
// instead of copying the original selection // instead of copying the original selection
select_div(div, selection); select_div($div, selection);
document.execCommand("copy"); document.execCommand("copy");
remove_div(div, ranges, selection); remove_div($div, ranges, selection);
} }
export function analyze_selection(selection) { export function analyze_selection(selection) {
@@ -200,9 +200,9 @@ export function analyze_selection(selection) {
let i; let i;
let range; let range;
const ranges = []; const ranges = [];
let startc; let $startc;
let endc; let $endc;
let initial_end_tr; let $initial_end_tr;
let start_id; let start_id;
let end_id; let end_id;
let start_data; let start_data;
@@ -216,10 +216,10 @@ export function analyze_selection(selection) {
range = selection.getRangeAt(i); range = selection.getRangeAt(i);
ranges.push(range); ranges.push(range);
startc = $(range.startContainer); $startc = $(range.startContainer);
start_data = find_boundary_tr( start_data = find_boundary_tr(
$(startc.parents(".selectable_row, .message_header")[0]), $($startc.parents(".selectable_row, .message_header")[0]),
(row) => row.next(), ($row) => $row.next(),
); );
if (start_data === undefined) { if (start_data === undefined) {
// Skip any selection sections that don't intersect a message. // Skip any selection sections that don't intersect a message.
@@ -231,21 +231,21 @@ export function analyze_selection(selection) {
start_id = start_data[0]; start_id = start_data[0];
} }
endc = $(range.endContainer); $endc = $(range.endContainer);
// If the selection ends in the bottom whitespace, we should // If the selection ends in the bottom whitespace, we should
// act as though the selection ends on the final message. // act as though the selection ends on the final message.
// This handles the issue that Chrome seems to like selecting // This handles the issue that Chrome seems to like selecting
// the compose_close button when you go off the end of the // the compose_close button when you go off the end of the
// last message // last message
if (endc.attr("id") === "bottom_whitespace" || endc.attr("id") === "compose_close") { if ($endc.attr("id") === "bottom_whitespace" || $endc.attr("id") === "compose_close") {
initial_end_tr = $(".message_row").last(); $initial_end_tr = $(".message_row").last();
// The selection goes off the end of the message feed, so // The selection goes off the end of the message feed, so
// this is a multi-message selection. // this is a multi-message selection.
skip_same_td_check = true; skip_same_td_check = true;
} else { } else {
initial_end_tr = $(endc.parents(".selectable_row")[0]); $initial_end_tr = $($endc.parents(".selectable_row")[0]);
} }
end_data = find_boundary_tr(initial_end_tr, (row) => row.prev()); end_data = find_boundary_tr($initial_end_tr, ($row) => $row.prev());
if (end_data === undefined) { if (end_data === undefined) {
// Skip any selection sections that don't intersect a message. // Skip any selection sections that don't intersect a message.

View File

@@ -4,8 +4,8 @@ export let csrf_token: string | undefined;
$(() => { $(() => {
// This requires that we used Jinja2's {% csrf_input %} somewhere on the page. // This requires that we used Jinja2's {% csrf_input %} somewhere on the page.
const csrf_input = $('input[name="csrfmiddlewaretoken"]'); const $csrf_input = $('input[name="csrfmiddlewaretoken"]');
csrf_token = csrf_input.attr("value"); csrf_token = $csrf_input.attr("value");
if (csrf_token === undefined) { if (csrf_token === undefined) {
return; return;
} }

View File

@@ -45,8 +45,8 @@ export function hide_dialog_spinner() {
$(".dialog_submit_button span").show(); $(".dialog_submit_button span").show();
$("#dialog_widget_modal .modal__btn").prop("disabled", false); $("#dialog_widget_modal .modal__btn").prop("disabled", false);
const spinner = $("#dialog_widget_modal .modal__spinner"); const $spinner = $("#dialog_widget_modal .modal__spinner");
loading.destroy_indicator(spinner); loading.destroy_indicator($spinner);
} }
export function show_dialog_spinner() { export function show_dialog_spinner() {
@@ -54,8 +54,8 @@ export function show_dialog_spinner() {
// Disable both the buttons. // Disable both the buttons.
$("#dialog_widget_modal .modal__btn").prop("disabled", true); $("#dialog_widget_modal .modal__btn").prop("disabled", true);
const spinner = $("#dialog_widget_modal .modal__spinner"); const $spinner = $("#dialog_widget_modal .modal__spinner");
loading.make_indicator(spinner); loading.make_indicator($spinner);
} }
// Supports a callback to be called once the modal finishes closing. // Supports a callback to be called once the modal finishes closing.
@@ -109,24 +109,24 @@ export function launch(conf) {
id: conf.id, id: conf.id,
single_footer_button: conf.single_footer_button, single_footer_button: conf.single_footer_button,
}); });
const dialog = $(html); const $dialog = $(html);
$("body").append(dialog); $("body").append($dialog);
if (conf.post_render !== undefined) { if (conf.post_render !== undefined) {
conf.post_render(); conf.post_render();
} }
const submit_button = dialog.find(".dialog_submit_button"); const $submit_button = $dialog.find(".dialog_submit_button");
// This is used to link the submit button with the form, if present, in the modal. // This is used to link the submit button with the form, if present, in the modal.
// This makes it so that submitting this form by pressing Enter on an input element // This makes it so that submitting this form by pressing Enter on an input element
// triggers a click on the submit button. // triggers a click on the submit button.
if (conf.form_id) { if (conf.form_id) {
submit_button.attr("form", conf.form_id); $submit_button.attr("form", conf.form_id);
} }
// Set up handlers. // Set up handlers.
submit_button.on("click", (e) => { $submit_button.on("click", (e) => {
if (conf.validate_input && !conf.validate_input(e)) { if (conf.validate_input && !conf.validate_input(e)) {
return; return;
} }
@@ -144,7 +144,7 @@ export function launch(conf) {
micromodal: true, micromodal: true,
on_show: () => { on_show: () => {
if (conf.focus_submit_on_open) { if (conf.focus_submit_on_open) {
submit_button.trigger("focus"); $submit_button.trigger("focus");
} }
if (conf.on_show) { if (conf.on_show) {
conf.on_show(); conf.on_show();

View File

@@ -30,8 +30,8 @@ import * as ui_util from "./ui_util";
import * as util from "./util"; import * as util from "./util";
function set_count(count) { function set_count(count) {
const drafts_li = $(".top_left_drafts"); const $drafts_li = $(".top_left_drafts");
ui_util.update_unread_count_in_dom(drafts_li, count); ui_util.update_unread_count_in_dom($drafts_li, count);
} }
export const draft_model = (function () { export const draft_model = (function () {
@@ -360,22 +360,22 @@ function row_with_focus() {
} }
function row_before_focus() { function row_before_focus() {
const focused_row = row_with_focus(); const $focused_row = row_with_focus();
return focused_row.prev(".draft-row:visible"); return $focused_row.prev(".draft-row:visible");
} }
function row_after_focus() { function row_after_focus() {
const focused_row = row_with_focus(); const $focused_row = row_with_focus();
return focused_row.next(".draft-row:visible"); return $focused_row.next(".draft-row:visible");
} }
function remove_draft(draft_row) { function remove_draft($draft_row) {
// Deletes the draft and removes it from the list // Deletes the draft and removes it from the list
const draft_id = draft_row.data("draft-id"); const draft_id = $draft_row.data("draft-id");
draft_model.deleteDraft(draft_id); draft_model.deleteDraft(draft_id);
draft_row.remove(); $draft_row.remove();
if ($("#drafts_table .draft-row").length === 0) { if ($("#drafts_table .draft-row").length === 0) {
$("#drafts_table .no-drafts").show(); $("#drafts_table .no-drafts").show();
@@ -407,15 +407,15 @@ export function launch() {
drafts, drafts,
draft_lifetime: DRAFT_LIFETIME, draft_lifetime: DRAFT_LIFETIME,
}); });
const drafts_table = $("#drafts_table"); const $drafts_table = $("#drafts_table");
drafts_table.append(rendered); $drafts_table.append(rendered);
if ($("#drafts_table .draft-row").length > 0) { if ($("#drafts_table .draft-row").length > 0) {
$("#drafts_table .no-drafts").hide(); $("#drafts_table .no-drafts").hide();
// Update possible dynamic elements. // Update possible dynamic elements.
const rendered_drafts = drafts_table.find( const $rendered_drafts = $drafts_table.find(
".message_content.rendered_markdown.restore-draft", ".message_content.rendered_markdown.restore-draft",
); );
rendered_drafts.each(function () { $rendered_drafts.each(function () {
rendered_markdown.update_elements($(this)); rendered_markdown.update_elements($(this));
}); });
} }
@@ -429,15 +429,15 @@ export function launch() {
e.stopPropagation(); e.stopPropagation();
const draft_row = $(this).closest(".draft-row"); const $draft_row = $(this).closest(".draft-row");
const draft_id = draft_row.data("draft-id"); const $draft_id = $draft_row.data("draft-id");
restore_draft(draft_id); restore_draft($draft_id);
}); });
$(".draft_controls .delete-draft").on("click", function () { $(".draft_controls .delete-draft").on("click", function () {
const draft_row = $(this).closest(".draft-row"); const $draft_row = $(this).closest(".draft-row");
remove_draft(draft_row); remove_draft($draft_row);
}); });
} }
@@ -489,35 +489,35 @@ function drafts_initialize_focus(event_name) {
activate_element(focus_element); activate_element(focus_element);
} }
function drafts_scroll(next_focus_draft_row) { function drafts_scroll($next_focus_draft_row) {
if (next_focus_draft_row[0] === undefined) { if ($next_focus_draft_row[0] === undefined) {
return; return;
} }
if (next_focus_draft_row[0].children[0] === undefined) { if ($next_focus_draft_row[0].children[0] === undefined) {
return; return;
} }
activate_element(next_focus_draft_row[0].children[0]); activate_element($next_focus_draft_row[0].children[0]);
// If focused draft is first draft, scroll to the top. // If focused draft is first draft, scroll to the top.
if ($(".draft-info-box").first()[0].parentElement === next_focus_draft_row[0]) { if ($(".draft-info-box").first()[0].parentElement === $next_focus_draft_row[0]) {
$(".drafts-list")[0].scrollTop = 0; $(".drafts-list")[0].scrollTop = 0;
} }
// If focused draft is the last draft, scroll to the bottom. // If focused draft is the last draft, scroll to the bottom.
if ($(".draft-info-box").last()[0].parentElement === next_focus_draft_row[0]) { if ($(".draft-info-box").last()[0].parentElement === $next_focus_draft_row[0]) {
$(".drafts-list")[0].scrollTop = $(".drafts-list")[0].scrollTop =
$(".drafts-list")[0].scrollHeight - $(".drafts-list").height(); $(".drafts-list")[0].scrollHeight - $(".drafts-list").height();
} }
// If focused draft is cut off from the top, scroll up halfway in draft modal. // If focused draft is cut off from the top, scroll up halfway in draft modal.
if (next_focus_draft_row.position().top < 55) { if ($next_focus_draft_row.position().top < 55) {
// 55 is the minimum distance from the top that will require extra scrolling. // 55 is the minimum distance from the top that will require extra scrolling.
$(".drafts-list")[0].scrollTop -= $(".drafts-list")[0].clientHeight / 2; $(".drafts-list")[0].scrollTop -= $(".drafts-list")[0].clientHeight / 2;
} }
// If focused draft is cut off from the bottom, scroll down halfway in draft modal. // If focused draft is cut off from the bottom, scroll down halfway in draft modal.
const dist_from_top = next_focus_draft_row.position().top; const dist_from_top = $next_focus_draft_row.position().top;
const total_dist = dist_from_top + next_focus_draft_row[0].clientHeight; const total_dist = dist_from_top + $next_focus_draft_row[0].clientHeight;
const dist_from_bottom = $(".drafts-container")[0].clientHeight - total_dist; const dist_from_bottom = $(".drafts-container")[0].clientHeight - total_dist;
if (dist_from_bottom < -4) { if (dist_from_bottom < -4) {
// -4 is the min dist from the bottom that will require extra scrolling. // -4 is the min dist from the bottom that will require extra scrolling.
@@ -545,17 +545,17 @@ export function drafts_handle_events(e, event_key) {
const focused_draft_id = row_with_focus().data("draft-id"); const focused_draft_id = row_with_focus().data("draft-id");
// Allows user to delete drafts with Backspace // Allows user to delete drafts with Backspace
if ((event_key === "backspace" || event_key === "delete") && focused_draft_id !== undefined) { if ((event_key === "backspace" || event_key === "delete") && focused_draft_id !== undefined) {
const draft_row = row_with_focus(); const $draft_row = row_with_focus();
const next_draft_row = row_after_focus(); const $next_draft_row = row_after_focus();
const prev_draft_row = row_before_focus(); const $prev_draft_row = row_before_focus();
let draft_to_be_focused_id; let draft_to_be_focused_id;
// Try to get the next draft in the list and 'focus' it // Try to get the next draft in the list and 'focus' it
// Use previous draft as a fallback // Use previous draft as a fallback
if (next_draft_row[0] !== undefined) { if ($next_draft_row[0] !== undefined) {
draft_to_be_focused_id = next_draft_row.data("draft-id"); draft_to_be_focused_id = $next_draft_row.data("draft-id");
} else if (prev_draft_row[0] !== undefined) { } else if ($prev_draft_row[0] !== undefined) {
draft_to_be_focused_id = prev_draft_row.data("draft-id"); draft_to_be_focused_id = $prev_draft_row.data("draft-id");
} }
const new_focus_element = document.querySelectorAll( const new_focus_element = document.querySelectorAll(
@@ -565,7 +565,7 @@ export function drafts_handle_events(e, event_key) {
activate_element(new_focus_element[0].children[0]); activate_element(new_focus_element[0].children[0]);
} }
remove_draft(draft_row); remove_draft($draft_row);
} }
// This handles when pressing Enter while looking at drafts. // This handles when pressing Enter while looking at drafts.
@@ -583,7 +583,7 @@ export function drafts_handle_events(e, event_key) {
export function open_overlay() { export function open_overlay() {
overlays.open_overlay({ overlays.open_overlay({
name: "drafts", name: "drafts",
overlay: $("#draft_overlay"), $overlay: $("#draft_overlay"),
on_close() { on_close() {
browser_history.exit_overlay(); browser_history.exit_overlay();
}, },

View File

@@ -40,19 +40,19 @@ export function DropdownListWidget({
this.setup(); this.setup();
} }
DropdownListWidget.prototype.render_default_text = function (elem) { DropdownListWidget.prototype.render_default_text = function ($elem) {
elem.text(this.default_text); $elem.text(this.default_text);
elem.addClass("text-warning"); $elem.addClass("text-warning");
elem.closest(".input-group").find(".dropdown_list_reset_button").hide(); $elem.closest(".input-group").find(".dropdown_list_reset_button").hide();
}; };
DropdownListWidget.prototype.render = function (value) { DropdownListWidget.prototype.render = function (value) {
$(`#${CSS.escape(this.container_id)} #${CSS.escape(this.value_id)}`).data("value", value); $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.value_id)}`).data("value", value);
const elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`); const $elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`);
if (!value || value === this.null_value) { if (!value || value === this.null_value) {
this.render_default_text(elem); this.render_default_text($elem);
return; return;
} }
@@ -60,14 +60,14 @@ DropdownListWidget.prototype.render = function (value) {
const item = this.data.find((x) => x.value === value.toString()); const item = this.data.find((x) => x.value === value.toString());
if (item === undefined) { if (item === undefined) {
this.render_default_text(elem); this.render_default_text($elem);
return; return;
} }
const text = this.render_text(item.name); const text = this.render_text(item.name);
elem.text(text); $elem.text(text);
elem.removeClass("text-warning"); $elem.removeClass("text-warning");
elem.closest(".input-group").find(".dropdown_list_reset_button").show(); $elem.closest(".input-group").find(".dropdown_list_reset_button").show();
}; };
DropdownListWidget.prototype.update = function (value) { DropdownListWidget.prototype.update = function (value) {
@@ -80,12 +80,12 @@ DropdownListWidget.prototype.register_event_handlers = function () {
"click keypress", "click keypress",
".list_item", ".list_item",
(e) => { (e) => {
const setting_elem = $(e.currentTarget).closest( const $setting_elem = $(e.currentTarget).closest(
`.${CSS.escape(this.widget_name)}_setting`, `.${CSS.escape(this.widget_name)}_setting`,
); );
if (e.type === "keypress") { if (e.type === "keypress") {
if (e.key === "Enter") { if (e.key === "Enter") {
setting_elem.find(".dropdown-menu").dropdown("toggle"); $setting_elem.find(".dropdown-menu").dropdown("toggle");
} else { } else {
return; return;
} }
@@ -101,10 +101,12 @@ DropdownListWidget.prototype.register_event_handlers = function () {
}; };
DropdownListWidget.prototype.setup_dropdown_widget = function (data) { DropdownListWidget.prototype.setup_dropdown_widget = function (data) {
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
const get_data = () => { const get_data = () => {
if (this.include_current_item) { if (this.include_current_item) {
return data; return data;
@@ -112,59 +114,63 @@ DropdownListWidget.prototype.setup_dropdown_widget = function (data) {
return data.filter((x) => x.value !== this.value.toString()); return data.filter((x) => x.value !== this.value.toString());
}; };
ListWidget.create(dropdown_list_body, get_data(data), { ListWidget.create($dropdown_list_body, get_data(data), {
name: `${CSS.escape(this.widget_name)}_list`, name: `${CSS.escape(this.widget_name)}_list`,
modifier(item) { modifier(item) {
return render_dropdown_list({item}); return render_dropdown_list({item});
}, },
filter: { filter: {
element: search_input, $element: $search_input,
predicate(item, value) { predicate(item, value) {
return item.name.toLowerCase().includes(value); return item.name.toLowerCase().includes(value);
}, },
}, },
simplebar_container: $(`#${CSS.escape(this.container_id)} .dropdown-list-wrapper`), $simplebar_container: $(`#${CSS.escape(this.container_id)} .dropdown-list-wrapper`),
}); });
}; };
// Sets the focus to the ListWidget input once the dropdown button is clicked. // Sets the focus to the ListWidget input once the dropdown button is clicked.
DropdownListWidget.prototype.dropdown_toggle_click_handler = function () { DropdownListWidget.prototype.dropdown_toggle_click_handler = function () {
const dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`); const $dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`);
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
dropdown_toggle.on("click", () => { $dropdown_toggle.on("click", () => {
search_input.val("").trigger("input"); $search_input.val("").trigger("input");
}); });
}; };
DropdownListWidget.prototype.dropdown_focus_events = function () { DropdownListWidget.prototype.dropdown_focus_events = function () {
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
const dropdown_menu = $(`.${CSS.escape(this.widget_name)}_setting .dropdown-menu`); `#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
const $dropdown_menu = $(`.${CSS.escape(this.widget_name)}_setting .dropdown-menu`);
const dropdown_elements = () => { const dropdown_elements = () => {
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
return dropdown_list_body.children().find("a"); return $dropdown_list_body.children().find("a");
}; };
// Rest of the key handlers are supported by our // Rest of the key handlers are supported by our
// bootstrap library. // bootstrap library.
dropdown_menu.on("keydown", (e) => { $dropdown_menu.on("keydown", (e) => {
function trigger_element_focus(element) { function trigger_element_focus($element) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
element.trigger("focus"); $element.trigger("focus");
} }
switch (e.key) { switch (e.key) {
case "ArrowDown": { case "ArrowDown": {
switch (e.target) { switch (e.target) {
case dropdown_elements().last()[0]: case dropdown_elements().last()[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
case search_input[0]: case $search_input[0]:
trigger_element_focus(dropdown_elements().first()); trigger_element_focus(dropdown_elements().first());
break; break;
} }
@@ -174,9 +180,9 @@ DropdownListWidget.prototype.dropdown_focus_events = function () {
case "ArrowUp": { case "ArrowUp": {
switch (e.target) { switch (e.target) {
case dropdown_elements().first()[0]: case dropdown_elements().first()[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
case search_input[0]: case $search_input[0]:
trigger_element_focus(dropdown_elements().last()); trigger_element_focus(dropdown_elements().last());
} }
@@ -184,11 +190,11 @@ DropdownListWidget.prototype.dropdown_focus_events = function () {
} }
case "Tab": { case "Tab": {
switch (e.target) { switch (e.target) {
case search_input[0]: case $search_input[0]:
trigger_element_focus(dropdown_elements().first()); trigger_element_focus(dropdown_elements().first());
break; break;
case dropdown_elements().last()[0]: case dropdown_elements().last()[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
} }
@@ -200,11 +206,13 @@ DropdownListWidget.prototype.dropdown_focus_events = function () {
DropdownListWidget.prototype.setup = function () { DropdownListWidget.prototype.setup = function () {
// populate the dropdown // populate the dropdown
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
const dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`); `#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
const $dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`);
this.setup_dropdown_widget(this.data); this.setup_dropdown_widget(this.data);
@@ -214,7 +222,7 @@ DropdownListWidget.prototype.setup = function () {
this.dropdown_toggle_click_handler(); this.dropdown_toggle_click_handler();
dropdown_toggle.on("focus", (e) => { $dropdown_toggle.on("focus", (e) => {
// On opening a Bootstrap Dropdown, the parent element receives focus. // On opening a Bootstrap Dropdown, the parent element receives focus.
// Here, we want our search input to have focus instead. // Here, we want our search input to have focus instead.
e.preventDefault(); e.preventDefault();
@@ -222,8 +230,8 @@ DropdownListWidget.prototype.setup = function () {
// dropdown, and only in the second call is the input // dropdown, and only in the second call is the input
// field visible in the DOM; so the following visibility // field visible in the DOM; so the following visibility
// check ensures we wait for the second call to focus. // check ensures we wait for the second call to focus.
if (dropdown_list_body.is(":visible")) { if ($dropdown_list_body.is(":visible")) {
search_input.trigger("focus"); $search_input.trigger("focus");
} }
}); });
@@ -292,15 +300,15 @@ MultiSelectDropdownListWidget.prototype.initialize_dropdown_values = function ()
if (!this.initial_value || this.initial_value === this.null_value) { if (!this.initial_value || this.initial_value === this.null_value) {
return; return;
} }
const elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`); const $elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`);
// Push values from initial valued array to `data_selected`. // Push values from initial valued array to `data_selected`.
this.data_selected.push(...this.initial_value); this.data_selected.push(...this.initial_value);
this.render_button_text(elem, this.limit); this.render_button_text($elem, this.limit);
}; };
// Set the button text as per the selected data. // Set the button text as per the selected data.
MultiSelectDropdownListWidget.prototype.render_button_text = function (elem, limit) { MultiSelectDropdownListWidget.prototype.render_button_text = function ($elem, limit) {
const items_selected = this.data_selected.length; const items_selected = this.data_selected.length;
let text = ""; let text = "";
@@ -308,7 +316,7 @@ MultiSelectDropdownListWidget.prototype.render_button_text = function (elem, lim
this.destroy_tooltip(); this.destroy_tooltip();
if (items_selected === 0) { if (items_selected === 0) {
this.render_default_text(elem); this.render_default_text($elem);
return; return;
} else if (limit >= items_selected) { } else if (limit >= items_selected) {
const data_selected = this.data.filter((data) => this.data_selected.includes(data.value)); const data_selected = this.data.filter((data) => this.data_selected.includes(data.value));
@@ -318,29 +326,31 @@ MultiSelectDropdownListWidget.prototype.render_button_text = function (elem, lim
this.render_tooltip(); this.render_tooltip();
} }
elem.text(text); $elem.text(text);
elem.removeClass("text-warning"); $elem.removeClass("text-warning");
elem.closest(".input-group").find(".dropdown_list_reset_button").show(); $elem.closest(".input-group").find(".dropdown_list_reset_button").show();
}; };
// Override the DrodownListWidget `render` function. // Override the DrodownListWidget `render` function.
MultiSelectDropdownListWidget.prototype.render = function (value) { MultiSelectDropdownListWidget.prototype.render = function (value) {
const elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`); const $elem = $(`#${CSS.escape(this.container_id)} #${CSS.escape(this.widget_name)}_name`);
if (!value || value === this.null_value) { if (!value || value === this.null_value) {
this.render_default_text(elem); this.render_default_text($elem);
return; return;
} }
this.render_button_text(elem, this.limit); this.render_button_text($elem, this.limit);
}; };
MultiSelectDropdownListWidget.prototype.dropdown_toggle_click_handler = function () { MultiSelectDropdownListWidget.prototype.dropdown_toggle_click_handler = function () {
const dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`); const $dropdown_toggle = $(`#${CSS.escape(this.container_id)} .dropdown-toggle`);
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
dropdown_toggle.on("click", () => { $dropdown_toggle.on("click", () => {
this.reset_dropdown_items(); this.reset_dropdown_items();
search_input.val("").trigger("input"); $search_input.val("").trigger("input");
}); });
}; };
@@ -372,12 +382,14 @@ MultiSelectDropdownListWidget.prototype.reset_dropdown_items = function () {
// Override the DrodownListWidget `setup_dropdown_widget` function. // Override the DrodownListWidget `setup_dropdown_widget` function.
MultiSelectDropdownListWidget.prototype.setup_dropdown_widget = function (data) { MultiSelectDropdownListWidget.prototype.setup_dropdown_widget = function (data) {
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
);
ListWidget.create(dropdown_list_body, data, { ListWidget.create($dropdown_list_body, data, {
name: `${CSS.escape(this.widget_name)}_list`, name: `${CSS.escape(this.widget_name)}_list`,
modifier(item) { modifier(item) {
return render_dropdown_list({item}); return render_dropdown_list({item});
@@ -386,51 +398,51 @@ MultiSelectDropdownListWidget.prototype.setup_dropdown_widget = function (data)
selected_items: this.data_selected, selected_items: this.data_selected,
}, },
filter: { filter: {
element: search_input, $element: $search_input,
predicate(item, value) { predicate(item, value) {
return item.name.toLowerCase().includes(value); return item.name.toLowerCase().includes(value);
}, },
}, },
simplebar_container: $(`#${CSS.escape(this.container_id)} .dropdown-list-wrapper`), $simplebar_container: $(`#${CSS.escape(this.container_id)} .dropdown-list-wrapper`),
}); });
}; };
// Add the check mark to dropdown element passed. // Add the check mark to dropdown element passed.
MultiSelectDropdownListWidget.prototype.add_check_mark = function (element) { MultiSelectDropdownListWidget.prototype.add_check_mark = function ($element) {
const value = element.attr("data-value"); const value = $element.attr("data-value");
const link_elem = element.find("a").expectOne(); const $link_elem = $element.find("a").expectOne();
link_elem.prepend($("<i>", {class: "fa fa-check"})); $link_elem.prepend($("<i>", {class: "fa fa-check"}));
element.addClass("checked"); $element.addClass("checked");
this.data_selected.push(value); this.data_selected.push(value);
}; };
// Remove the check mark from dropdown element. // Remove the check mark from dropdown element.
MultiSelectDropdownListWidget.prototype.remove_check_mark = function (element) { MultiSelectDropdownListWidget.prototype.remove_check_mark = function ($element) {
const icon = element.find("i").expectOne(); const $icon = $element.find("i").expectOne();
const value = element.attr("data-value"); const value = $element.attr("data-value");
const index = this.data_selected.indexOf(value); const index = this.data_selected.indexOf(value);
if (index > -1) { if (index > -1) {
icon.remove(); $icon.remove();
element.removeClass("checked"); $element.removeClass("checked");
this.data_selected.splice(index, 1); this.data_selected.splice(index, 1);
} }
}; };
// Render the tooltip once the text changes to `n` selected. // Render the tooltip once the text changes to `n` selected.
MultiSelectDropdownListWidget.prototype.render_tooltip = function () { MultiSelectDropdownListWidget.prototype.render_tooltip = function () {
const elem = $(`#${CSS.escape(this.container_id)}`); const $elem = $(`#${CSS.escape(this.container_id)}`);
const selected_items = this.data.filter((item) => this.checked_items.includes(item.value)); const selected_items = this.data.filter((item) => this.checked_items.includes(item.value));
tippy(elem[0], { tippy($elem[0], {
content: selected_items.map((item) => item.name).join(", "), content: selected_items.map((item) => item.name).join(", "),
placement: "top", placement: "top",
}); });
}; };
MultiSelectDropdownListWidget.prototype.destroy_tooltip = function () { MultiSelectDropdownListWidget.prototype.destroy_tooltip = function () {
const elem = $(`#${CSS.escape(this.container_id)}`); const $elem = $(`#${CSS.escape(this.container_id)}`);
const tippy_instance = elem[0]._tippy; const tippy_instance = $elem[0]._tippy;
if (!tippy_instance) { if (!tippy_instance) {
return; return;
} }
@@ -442,35 +454,37 @@ MultiSelectDropdownListWidget.prototype.dropdown_focus_events = function () {
// Main keydown event handler which transfers the focus from one child element // Main keydown event handler which transfers the focus from one child element
// to another. // to another.
const search_input = $(`#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`); const $search_input = $(
const dropdown_menu = $(`.${CSS.escape(this.widget_name)}_setting .dropdown-menu`); `#${CSS.escape(this.container_id)} .dropdown-search > input[type=text]`,
const filter_button = $(`#${CSS.escape(this.container_id)} .multiselect_btn`); );
const $dropdown_menu = $(`.${CSS.escape(this.widget_name)}_setting .dropdown-menu`);
const $filter_button = $(`#${CSS.escape(this.container_id)} .multiselect_btn`);
const dropdown_elements = () => { const dropdown_elements = () => {
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
return dropdown_list_body.children().find("a"); return $dropdown_list_body.children().find("a");
}; };
dropdown_menu.on("keydown", (e) => { $dropdown_menu.on("keydown", (e) => {
function trigger_element_focus(element) { function trigger_element_focus($element) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
element.trigger("focus"); $element.trigger("focus");
} }
switch (e.key) { switch (e.key) {
case "ArrowDown": { case "ArrowDown": {
switch (e.target) { switch (e.target) {
case dropdown_elements().last()[0]: case dropdown_elements().last()[0]:
trigger_element_focus(filter_button); trigger_element_focus($filter_button);
break; break;
case $(`#${CSS.escape(this.container_id)} .multiselect_btn`)[0]: case $(`#${CSS.escape(this.container_id)} .multiselect_btn`)[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
case search_input[0]: case $search_input[0]:
trigger_element_focus(dropdown_elements().first()); trigger_element_focus(dropdown_elements().first());
break; break;
} }
@@ -480,10 +494,10 @@ MultiSelectDropdownListWidget.prototype.dropdown_focus_events = function () {
case "ArrowUp": { case "ArrowUp": {
switch (e.target) { switch (e.target) {
case dropdown_elements().first()[0]: case dropdown_elements().first()[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
case search_input[0]: case $search_input[0]:
trigger_element_focus(filter_button); trigger_element_focus($filter_button);
break; break;
case $(`#${CSS.escape(this.container_id)} .multiselect_btn`)[0]: case $(`#${CSS.escape(this.container_id)} .multiselect_btn`)[0]:
trigger_element_focus(dropdown_elements().last()); trigger_element_focus(dropdown_elements().last());
@@ -494,11 +508,11 @@ MultiSelectDropdownListWidget.prototype.dropdown_focus_events = function () {
} }
case "Tab": { case "Tab": {
switch (e.target) { switch (e.target) {
case search_input[0]: case $search_input[0]:
trigger_element_focus(dropdown_elements().first()); trigger_element_focus(dropdown_elements().first());
break; break;
case filter_button[0]: case $filter_button[0]:
trigger_element_focus(search_input); trigger_element_focus($search_input);
break; break;
} }
@@ -510,20 +524,20 @@ MultiSelectDropdownListWidget.prototype.dropdown_focus_events = function () {
// Override the `register_event_handlers` function. // Override the `register_event_handlers` function.
MultiSelectDropdownListWidget.prototype.register_event_handlers = function () { MultiSelectDropdownListWidget.prototype.register_event_handlers = function () {
const dropdown_list_body = $( const $dropdown_list_body = $(
`#${CSS.escape(this.container_id)} .dropdown-list-body`, `#${CSS.escape(this.container_id)} .dropdown-list-body`,
).expectOne(); ).expectOne();
dropdown_list_body.on("click keypress", ".list_item", (e) => { $dropdown_list_body.on("click keypress", ".list_item", (e) => {
if (e.type === "keypress" && e.key !== "Enter") { if (e.type === "keypress" && e.key !== "Enter") {
return; return;
} }
const element = $(e.target.closest("li")); const $element = $(e.target.closest("li"));
if (element.hasClass("checked")) { if ($element.hasClass("checked")) {
this.remove_check_mark(element); this.remove_check_mark($element);
} else { } else {
this.add_check_mark(element); this.add_check_mark($element);
} }
e.stopPropagation(); e.stopPropagation();
@@ -556,10 +570,10 @@ MultiSelectDropdownListWidget.prototype.register_event_handlers = function () {
// the dropdown is closed. // the dropdown is closed.
if (this.on_close) { if (this.on_close) {
e.stopPropagation(); e.stopPropagation();
const setting_elem = $(e.currentTarget).closest( const $setting_elem = $(e.currentTarget).closest(
`.${CSS.escape(this.widget_name)}_setting`, `.${CSS.escape(this.widget_name)}_setting`,
); );
setting_elem.find(".dropdown-menu").dropdown("toggle"); $setting_elem.find(".dropdown-menu").dropdown("toggle");
this.on_close(); this.on_close();
} }

View File

@@ -35,21 +35,21 @@ let waiting_for_ack = new Map();
// These retry spinner functions return true if and only if the // These retry spinner functions return true if and only if the
// spinner already is in the requested state, which can be used to // spinner already is in the requested state, which can be used to
// avoid sending duplicate requests. // avoid sending duplicate requests.
function show_retry_spinner(row) { function show_retry_spinner($row) {
const retry_spinner = row.find(".refresh-failed-message"); const $retry_spinner = $row.find(".refresh-failed-message");
if (!retry_spinner.hasClass("rotating")) { if (!$retry_spinner.hasClass("rotating")) {
retry_spinner.toggleClass("rotating", true); $retry_spinner.toggleClass("rotating", true);
return false; return false;
} }
return true; return true;
} }
function hide_retry_spinner(row) { function hide_retry_spinner($row) {
const retry_spinner = row.find(".refresh-failed-message"); const $retry_spinner = $row.find(".refresh-failed-message");
if (retry_spinner.hasClass("rotating")) { if ($retry_spinner.hasClass("rotating")) {
retry_spinner.toggleClass("rotating", false); $retry_spinner.toggleClass("rotating", false);
return false; return false;
} }
return true; return true;
@@ -67,9 +67,9 @@ function failed_message_success(message_id) {
ui.show_failed_message_success(message_id); ui.show_failed_message_success(message_id);
} }
function resend_message(message, row) { function resend_message(message, $row) {
message.content = message.raw_content; message.content = message.raw_content;
if (show_retry_spinner(row)) { if (show_retry_spinner($row)) {
// retry already in in progress // retry already in in progress
return; return;
} }
@@ -84,7 +84,7 @@ function resend_message(message, row) {
const message_id = data.id; const message_id = data.id;
const locally_echoed = true; const locally_echoed = true;
hide_retry_spinner(row); hide_retry_spinner($row);
compose.send_message_success(local_id, message_id, locally_echoed); compose.send_message_success(local_id, message_id, locally_echoed);
@@ -95,7 +95,7 @@ function resend_message(message, row) {
function on_error(response) { function on_error(response) {
message_send_error(message.id, response); message_send_error(message.id, response);
setTimeout(() => { setTimeout(() => {
hide_retry_spinner(row); hide_retry_spinner($row);
}, 300); }, 300);
blueslip.log("Manual resend of message failed"); blueslip.log("Manual resend of message failed");
} }
@@ -470,8 +470,8 @@ export function initialize() {
$("#main_div").on("click", selector, function (e) { $("#main_div").on("click", selector, function (e) {
e.stopPropagation(); e.stopPropagation();
popovers.hide_all(); popovers.hide_all();
const row = $(this).closest(".message_row"); const $row = $(this).closest(".message_row");
const local_id = rows.local_echo_id(row); const local_id = rows.local_echo_id($row);
// Message should be waiting for ack and only have a local id, // Message should be waiting for ack and only have a local id,
// otherwise send would not have failed // otherwise send would not have failed
const message = waiting_for_ack.get(local_id); const message = waiting_for_ack.get(local_id);
@@ -482,7 +482,7 @@ export function initialize() {
); );
return; return;
} }
callback(message, row); callback(message, $row);
}); });
} }

View File

@@ -29,7 +29,7 @@ const APPROX_WIDTH = 255;
// implemented as the emoji_popover. // implemented as the emoji_popover.
export let complete_emoji_catalog = []; export let complete_emoji_catalog = [];
let current_message_emoji_popover_elem; let $current_message_emoji_popover_elem;
let emoji_catalog_last_coordinates = { let emoji_catalog_last_coordinates = {
section: 0, section: 0,
index: 0, index: 0,
@@ -175,9 +175,9 @@ const generate_emoji_picker_content = function (id) {
}); });
}; };
function refill_section_head_offsets(popover) { function refill_section_head_offsets($popover) {
section_head_offsets = []; section_head_offsets = [];
popover.find(".emoji-popover-subheading").each(function () { $popover.find(".emoji-popover-subheading").each(function () {
section_head_offsets.push({ section_head_offsets.push({
section: $(this).attr("data-section"), section: $(this).attr("data-section"),
position_y: $(this).position().top, position_y: $(this).position().top,
@@ -186,7 +186,7 @@ function refill_section_head_offsets(popover) {
} }
export function reactions_popped() { export function reactions_popped() {
return current_message_emoji_popover_elem !== undefined; return $current_message_emoji_popover_elem !== undefined;
} }
export function hide_emoji_popover() { export function hide_emoji_popover() {
@@ -198,9 +198,9 @@ export function hide_emoji_popover() {
$(".app, .header, .modal__overlay, #set_user_status_modal").css("pointer-events", "all"); $(".app, .header, .modal__overlay, #set_user_status_modal").css("pointer-events", "all");
} }
if (reactions_popped()) { if (reactions_popped()) {
current_message_emoji_popover_elem.popover("destroy"); $current_message_emoji_popover_elem.popover("destroy");
current_message_emoji_popover_elem.removeClass("reaction_button_visible"); $current_message_emoji_popover_elem.removeClass("reaction_button_visible");
current_message_emoji_popover_elem = undefined; $current_message_emoji_popover_elem = undefined;
} }
} }
@@ -210,16 +210,16 @@ function get_selected_emoji() {
function get_rendered_emoji(section, index) { function get_rendered_emoji(section, index) {
const emoji_id = get_emoji_id(section, index); const emoji_id = get_emoji_id(section, index);
const emoji = $(`.emoji-popover-emoji[data-emoji-id='${CSS.escape(emoji_id)}']`); const $emoji = $(`.emoji-popover-emoji[data-emoji-id='${CSS.escape(emoji_id)}']`);
if (emoji.length > 0) { if ($emoji.length > 0) {
return emoji; return $emoji;
} }
return undefined; return undefined;
} }
function filter_emojis() { function filter_emojis() {
const elt = $(".emoji-popover-filter").expectOne(); const $elt = $(".emoji-popover-filter").expectOne();
const query = elt.val().trim().toLowerCase(); const query = $elt.val().trim().toLowerCase();
const message_id = $(".emoji-search-results-container").data("message-id"); const message_id = $(".emoji-search-results-container").data("message-id");
const search_results_visible = $(".emoji-search-results-container").is(":visible"); const search_results_visible = $(".emoji-search-results-container").is(":visible");
if (query !== "") { if (query !== "") {
@@ -288,12 +288,12 @@ function is_status_emoji(emoji) {
function process_enter_while_filtering(e) { function process_enter_while_filtering(e) {
if (e.key === "Enter") { if (e.key === "Enter") {
e.preventDefault(); e.preventDefault();
const first_emoji = get_rendered_emoji(0, 0); const $first_emoji = get_rendered_emoji(0, 0);
if (first_emoji) { if ($first_emoji) {
if (is_composition(first_emoji)) { if (is_composition($first_emoji)) {
first_emoji.trigger("click"); $first_emoji.trigger("click");
} else { } else {
toggle_reaction(first_emoji.attr("data-emoji-name"), e); toggle_reaction($first_emoji.attr("data-emoji-name"), e);
} }
} }
} }
@@ -345,20 +345,20 @@ function update_emoji_showcase($focused_emoji) {
} }
function maybe_change_focused_emoji($emoji_map, next_section, next_index, preserve_scroll) { function maybe_change_focused_emoji($emoji_map, next_section, next_index, preserve_scroll) {
const next_emoji = get_rendered_emoji(next_section, next_index); const $next_emoji = get_rendered_emoji(next_section, next_index);
if (next_emoji) { if ($next_emoji) {
current_section = next_section; current_section = next_section;
current_index = next_index; current_index = next_index;
if (!preserve_scroll) { if (!preserve_scroll) {
next_emoji.trigger("focus"); $next_emoji.trigger("focus");
} else { } else {
const start = ui.get_scroll_element($emoji_map).scrollTop(); const start = ui.get_scroll_element($emoji_map).scrollTop();
next_emoji.trigger("focus"); $next_emoji.trigger("focus");
if (ui.get_scroll_element($emoji_map).scrollTop() !== start) { if (ui.get_scroll_element($emoji_map).scrollTop() !== start) {
ui.get_scroll_element($emoji_map).scrollTop(start); ui.get_scroll_element($emoji_map).scrollTop(start);
} }
} }
update_emoji_showcase(next_emoji); update_emoji_showcase($next_emoji);
return true; return true;
} }
return false; return false;
@@ -449,7 +449,7 @@ export function navigate(event_name, e) {
const $popover = $(".emoji-popover").expectOne(); const $popover = $(".emoji-popover").expectOne();
const $emoji_map = $popover.find(".emoji-popover-emoji-map").expectOne(); const $emoji_map = $popover.find(".emoji-popover-emoji-map").expectOne();
const selected_emoji = get_rendered_emoji(current_section, current_index); const $selected_emoji = get_rendered_emoji(current_section, current_index);
const is_filter_focused = $(".emoji-popover-filter").is(":focus"); const is_filter_focused = $(".emoji-popover-filter").is(":focus");
// special cases // special cases
if (is_filter_focused) { if (is_filter_focused) {
@@ -457,16 +457,16 @@ export function navigate(event_name, e) {
const filter_text = $(".emoji-popover-filter").val(); const filter_text = $(".emoji-popover-filter").val();
const is_cursor_at_end = $(".emoji-popover-filter").caret() === filter_text.length; const is_cursor_at_end = $(".emoji-popover-filter").caret() === filter_text.length;
if (event_name === "down_arrow" || (is_cursor_at_end && event_name === "right_arrow")) { if (event_name === "down_arrow" || (is_cursor_at_end && event_name === "right_arrow")) {
selected_emoji.trigger("focus"); $selected_emoji.trigger("focus");
if (current_section === 0 && current_index < 6) { if (current_section === 0 && current_index < 6) {
ui.get_scroll_element($emoji_map).scrollTop(0); ui.get_scroll_element($emoji_map).scrollTop(0);
} }
update_emoji_showcase(selected_emoji); update_emoji_showcase($selected_emoji);
return true; return true;
} }
if (event_name === "tab") { if (event_name === "tab") {
selected_emoji.trigger("focus"); $selected_emoji.trigger("focus");
update_emoji_showcase(selected_emoji); update_emoji_showcase($selected_emoji);
return true; return true;
} }
return false; return false;
@@ -474,7 +474,7 @@ export function navigate(event_name, e) {
(current_section === 0 && current_index < 6 && event_name === "up_arrow") || (current_section === 0 && current_index < 6 && event_name === "up_arrow") ||
(current_section === 0 && current_index === 0 && event_name === "left_arrow") (current_section === 0 && current_index === 0 && event_name === "left_arrow")
) { ) {
if (selected_emoji) { if ($selected_emoji) {
// In this case, we're move up into the reaction // In this case, we're move up into the reaction
// filter. Here, we override the default browser // filter. Here, we override the default browser
// behavior, which in Firefox is good (preserving // behavior, which in Firefox is good (preserving
@@ -531,8 +531,8 @@ function process_keypress(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const emoji_filter = $(".emoji-popover-filter"); const $emoji_filter = $(".emoji-popover-filter");
const old_query = emoji_filter.val(); const old_query = $emoji_filter.val();
let new_query = ""; let new_query = "";
if (pressed_key === 8) { if (pressed_key === 8) {
@@ -544,16 +544,16 @@ function process_keypress(e) {
new_query = old_query + key_str; new_query = old_query + key_str;
} }
emoji_filter.val(new_query); $emoji_filter.val(new_query);
change_focus_to_filter(); change_focus_to_filter();
filter_emojis(); filter_emojis();
} }
} }
export function emoji_select_tab(elt) { export function emoji_select_tab($elt) {
const scrolltop = elt.scrollTop(); const scrolltop = $elt.scrollTop();
const scrollheight = elt.prop("scrollHeight"); const scrollheight = $elt.prop("scrollHeight");
const elt_height = elt.height(); const elt_height = $elt.height();
let currently_selected = ""; let currently_selected = "";
for (const o of section_head_offsets) { for (const o of section_head_offsets) {
if (scrolltop + elt_height / 2 >= o.position_y) { if (scrolltop + elt_height / 2 >= o.position_y) {
@@ -577,8 +577,8 @@ export function emoji_select_tab(elt) {
} }
} }
function register_popover_events(popover) { function register_popover_events($popover) {
const $emoji_map = popover.find(".emoji-popover-emoji-map"); const $emoji_map = $popover.find(".emoji-popover-emoji-map");
ui.get_scroll_element($emoji_map).on("scroll", () => { ui.get_scroll_element($emoji_map).on("scroll", () => {
emoji_select_tab(ui.get_scroll_element($emoji_map)); emoji_select_tab(ui.get_scroll_element($emoji_map));
@@ -598,11 +598,11 @@ function register_popover_events(popover) {
}); });
} }
export function build_emoji_popover(elt, id) { export function build_emoji_popover($elt, id) {
const template_args = { const template_args = {
class: "emoji-info-popover", class: "emoji-info-popover",
}; };
let placement = popovers.compute_placement(elt, APPROX_HEIGHT, APPROX_WIDTH, true); let placement = popovers.compute_placement($elt, APPROX_HEIGHT, APPROX_WIDTH, true);
if (placement === "viewport_center") { if (placement === "viewport_center") {
// For legacy reasons `compute_placement` actually can // For legacy reasons `compute_placement` actually can
@@ -619,7 +619,7 @@ export function build_emoji_popover(elt, id) {
template = "<div class='popover-flex'>" + template + "</div>"; template = "<div class='popover-flex'>" + template + "</div>";
} }
elt.popover({ $elt.popover({
// temporary patch for handling popover placement of `viewport_center` // temporary patch for handling popover placement of `viewport_center`
placement, placement,
fix_positions: true, fix_positions: true,
@@ -629,11 +629,11 @@ export function build_emoji_popover(elt, id) {
html: true, html: true,
trigger: "manual", trigger: "manual",
}); });
elt.popover("show"); $elt.popover("show");
const popover = elt.data("popover").$tip; const $popover = $elt.data("popover").$tip;
popover.find(".emoji-popover-filter").trigger("focus"); $popover.find(".emoji-popover-filter").trigger("focus");
current_message_emoji_popover_elem = elt; $current_message_emoji_popover_elem = $elt;
emoji_catalog_last_coordinates = { emoji_catalog_last_coordinates = {
section: 0, section: 0,
@@ -641,31 +641,31 @@ export function build_emoji_popover(elt, id) {
}; };
show_emoji_catalog(); show_emoji_catalog();
elt.ready(() => refill_section_head_offsets(popover)); $elt.ready(() => refill_section_head_offsets($popover));
register_popover_events(popover); register_popover_events($popover);
} }
export function toggle_emoji_popover(element, id) { export function toggle_emoji_popover(element, id) {
const last_popover_elem = current_message_emoji_popover_elem; const $last_popover_elem = $current_message_emoji_popover_elem;
popovers.hide_all(); popovers.hide_all();
if (last_popover_elem !== undefined && last_popover_elem.get()[0] === element) { if ($last_popover_elem !== undefined && $last_popover_elem.get()[0] === element) {
// We want it to be the case that a user can dismiss a popover // We want it to be the case that a user can dismiss a popover
// by clicking on the same element that caused the popover. // by clicking on the same element that caused the popover.
return; return;
} }
$(element).closest(".message_row").toggleClass("has_popover has_emoji_popover"); $(element).closest(".message_row").toggleClass("has_popover has_emoji_popover");
const elt = $(element); const $elt = $(element);
if (id !== undefined) { if (id !== undefined) {
message_lists.current.select_id(id); message_lists.current.select_id(id);
} }
if (user_status_ui.user_status_picker_open()) { if (user_status_ui.user_status_picker_open()) {
build_emoji_popover(elt, id, true); build_emoji_popover($elt, id, true);
} else if (elt.data("popover") === undefined) { } else if ($elt.data("popover") === undefined) {
// Keep the element over which the popover is based off visible. // Keep the element over which the popover is based off visible.
elt.addClass("reaction_button_visible"); $elt.addClass("reaction_button_visible");
build_emoji_popover(elt, id); build_emoji_popover($elt, id);
} }
reset_emoji_showcase(); reset_emoji_showcase();
} }
@@ -686,13 +686,13 @@ export function register_click_handlers() {
// The following check will return false if emoji was not selected in // The following check will return false if emoji was not selected in
// message edit form. // message edit form.
if (edit_message_id !== null) { if (edit_message_id !== null) {
const edit_message_textarea = $( const $edit_message_textarea = $(
`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`, `#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`,
); );
// Assign null to edit_message_id so that the selection of emoji in new // Assign null to edit_message_id so that the selection of emoji in new
// message composition form works correctly. // message composition form works correctly.
edit_message_id = null; edit_message_id = null;
compose_ui.insert_syntax_and_focus(emoji_text, edit_message_textarea); compose_ui.insert_syntax_and_focus(emoji_text, $edit_message_textarea);
} else { } else {
compose_ui.insert_syntax_and_focus(emoji_text); compose_ui.insert_syntax_and_focus(emoji_text);
} }

View File

@@ -10,9 +10,9 @@ function is_numeric_key(key) {
} }
export function show_flatpickr(element, callback, default_timestamp, options = {}) { export function show_flatpickr(element, callback, default_timestamp, options = {}) {
const flatpickr_input = $("<input id='#timestamp_flatpickr'>"); const $flatpickr_input = $("<input id='#timestamp_flatpickr'>");
const instance = flatpickr_input.flatpickr({ const instance = $flatpickr_input.flatpickr({
mode: "single", mode: "single",
enableTime: true, enableTime: true,
clickOpens: false, clickOpens: false,
@@ -59,9 +59,9 @@ export function show_flatpickr(element, callback, default_timestamp, options = {
...options, ...options,
}); });
const container = $($(instance.innerContainer).parent()); const $container = $($(instance.innerContainer).parent());
container.on("keydown", (e) => { $container.on("keydown", (e) => {
if (is_numeric_key(e.key)) { if (is_numeric_key(e.key)) {
// Let users type numeric values // Let users type numeric values
return true; return true;
@@ -83,7 +83,7 @@ export function show_flatpickr(element, callback, default_timestamp, options = {
return true; // use flatpickr default implementation return true; // use flatpickr default implementation
} }
$(element).toggleClass("has_popover"); $(element).toggleClass("has_popover");
container.find(".flatpickr-confirm").trigger("click"); $container.find(".flatpickr-confirm").trigger("click");
} }
if (hotkey.name === "escape") { if (hotkey.name === "escape") {
@@ -106,8 +106,8 @@ export function show_flatpickr(element, callback, default_timestamp, options = {
return true; return true;
}); });
container.on("click", ".flatpickr-confirm", () => { $container.on("click", ".flatpickr-confirm", () => {
callback(flatpickr_input.val()); callback($flatpickr_input.val());
instance.close(); instance.close();
instance.destroy(); instance.destroy();
}); });

View File

@@ -8,28 +8,28 @@ import * as timerender from "./timerender";
let is_floating_recipient_bar_showing = false; let is_floating_recipient_bar_showing = false;
function top_offset(elem) { function top_offset($elem) {
return ( return (
elem.offset().top - $elem.offset().top -
$("#message_view_header").safeOuterHeight() - $("#message_view_header").safeOuterHeight() -
$("#navbar_alerts_wrapper").height() $("#navbar_alerts_wrapper").height()
); );
} }
export function first_visible_message(bar) { export function first_visible_message($bar) {
// The first truly visible message would be computed using the // The first truly visible message would be computed using the
// bottom of the floating recipient bar; but we want the date from // bottom of the floating recipient bar; but we want the date from
// the first visible message were the floating recipient bar not // the first visible message were the floating recipient bar not
// displayed, which will always be the first messages whose bottom // displayed, which will always be the first messages whose bottom
// overlaps the floating recipient bar's space (since you ). // overlaps the floating recipient bar's space (since you ).
const messages = bar.children(".message_row"); const $messages = $bar.children(".message_row");
const frb = $("#floating_recipient_bar"); const $frb = $("#floating_recipient_bar");
const frb_top = top_offset(frb); const frb_top = top_offset($frb);
const frb_bottom = frb_top + frb.safeOuterHeight(); const frb_bottom = frb_top + $frb.safeOuterHeight();
let result; let $result;
for (const message_element of messages) { for (const message_element of $messages) {
// The details of this comparison function are sensitive, since we're // The details of this comparison function are sensitive, since we're
// balancing between three possible bugs: // balancing between three possible bugs:
// //
@@ -56,40 +56,40 @@ export function first_visible_message(bar) {
// message_viewport.scrollTop() to set precise scrolling // message_viewport.scrollTop() to set precise scrolling
// positions determines the value for date_bar_height_offset. // positions determines the value for date_bar_height_offset.
let message = $(message_element); let $message = $(message_element);
const message_bottom = top_offset(message) + message.safeOuterHeight(); const message_bottom = top_offset($message) + $message.safeOuterHeight();
const date_bar_height_offset = 10; const date_bar_height_offset = 10;
if (message_bottom > frb_top) { if (message_bottom > frb_top) {
result = message; $result = $message;
} }
// Important: This will break if we ever have things that are // Important: This will break if we ever have things that are
// not message rows inside a recipient_row block. // not message rows inside a recipient_row block.
message = message.next(".message_row"); $message = $message.next(".message_row");
if ( if (
message.length > 0 && $message.length > 0 &&
result && $result &&
// Before returning a result, we check whether the next // Before returning a result, we check whether the next
// message's top is actually below the bottom of the // message's top is actually below the bottom of the
// floating recipient bar; this is different from the // floating recipient bar; this is different from the
// bottom of our current message because there may be a // bottom of our current message because there may be a
// between-messages date separator row in between. // between-messages date separator row in between.
top_offset(message) < frb_bottom - date_bar_height_offset top_offset($message) < frb_bottom - date_bar_height_offset
) { ) {
result = message; $result = $message;
} }
if (result) { if ($result) {
return result; return $result;
} }
} }
// If none of the messages are visible, just take the last message. // If none of the messages are visible, just take the last message.
return messages.last(); return $messages.last();
} }
export function get_date(elem) { export function get_date($elem) {
const message_row = first_visible_message(elem); const message_row = first_visible_message($elem);
if (!message_row || !message_row.length) { if (!message_row || !message_row.length) {
return undefined; return undefined;
@@ -123,39 +123,39 @@ export function relevant_recipient_bars() {
// not exactly where we want. The value we get // not exactly where we want. The value we get
// may be be too far up in the feed, but we can // may be be too far up in the feed, but we can
// deal with that later. // deal with that later.
let first_elem = candidate_recipient_bar(); let $first_elem = candidate_recipient_bar();
if (!first_elem) { if (!$first_elem) {
first_elem = $(".focused_table").find(".recipient_row").first(); $first_elem = $(".focused_table").find(".recipient_row").first();
} }
if (first_elem.length === 0) { if ($first_elem.length === 0) {
return []; return [];
} }
elems.push(first_elem); elems.push($first_elem);
const max_offset = top_offset($("#compose")); const max_offset = top_offset($("#compose"));
let header_height = first_elem.find(".message_header").safeOuterHeight(); let header_height = $first_elem.find(".message_header").safeOuterHeight();
// It's okay to overestimate header_height a bit, as we don't // It's okay to overestimate header_height a bit, as we don't
// really need an FRB for a section that barely shows. // really need an FRB for a section that barely shows.
header_height += 10; header_height += 10;
function next(elem) { function next($elem) {
elem = elem.next(); $elem = $elem.next();
while (elem.length !== 0 && !elem.hasClass("recipient_row")) { while ($elem.length !== 0 && !$elem.hasClass("recipient_row")) {
elem = elem.next(); $elem = $elem.next();
} }
return elem; return $elem;
} }
// Now start the forward traversal of recipient bars. // Now start the forward traversal of recipient bars.
// We'll stop when we go below the fold. // We'll stop when we go below the fold.
let elem = next(first_elem); let $elem = next($first_elem);
while (elem.length) { while ($elem.length) {
if (top_offset(elem) < header_height) { if (top_offset($elem) < header_height) {
// If we are close to the top, then the prior // If we are close to the top, then the prior
// elements we found are no longer relevant, // elements we found are no longer relevant,
// because either the selected item we started // because either the selected item we started
@@ -165,15 +165,15 @@ export function relevant_recipient_bars() {
elems = []; elems = [];
} }
if (top_offset(elem) > max_offset) { if (top_offset($elem) > max_offset) {
// Out of sight, out of mind! // Out of sight, out of mind!
// (The element is below the fold, so we stop the // (The element is below the fold, so we stop the
// traversal.) // traversal.)
break; break;
} }
elems.push(elem); elems.push($elem);
elem = next(elem); $elem = next($elem);
} }
if (elems.length === 0) { if (elems.length === 0) {
@@ -181,25 +181,25 @@ export function relevant_recipient_bars() {
return []; return [];
} }
const items = elems.map((elem, i) => { const items = elems.map(($elem, i) => {
let date_html; let date_html;
let need_frb; let need_frb;
if (i === 0) { if (i === 0) {
date_html = get_date(elem); date_html = get_date($elem);
need_frb = top_offset(elem) < 0; need_frb = top_offset($elem) < 0;
} else { } else {
date_html = elem.find(".recipient_row_date").html(); date_html = $elem.find(".recipient_row_date").html();
need_frb = false; need_frb = false;
} }
const date_text = $(date_html).text(); const date_text = $(date_html).text();
// Add title here to facilitate troubleshooting. // Add title here to facilitate troubleshooting.
const title = elem.find(".message_label_clickable").last().attr("title"); const title = $elem.find(".message_label_clickable").last().attr("title");
const item = { const item = {
elem, $elem,
title, title,
date_html, date_html,
date_text, date_text,
@@ -236,25 +236,25 @@ export function candidate_recipient_bar() {
// bars that is still above the fold. // bars that is still above the fold.
// Start with the pointer's current location. // Start with the pointer's current location.
const selected_row = message_lists.current.selected_row(); const $selected_row = message_lists.current.selected_row();
if (selected_row === undefined || selected_row.length === 0) { if ($selected_row === undefined || $selected_row.length === 0) {
return undefined; return undefined;
} }
let candidate = rows.get_message_recipient_row(selected_row); let $candidate = rows.get_message_recipient_row($selected_row);
if (candidate === undefined) { if ($candidate === undefined) {
return undefined; return undefined;
} }
while (candidate.length) { while ($candidate.length) {
if (candidate.hasClass("recipient_row") && top_offset(candidate) < 0) { if ($candidate.hasClass("recipient_row") && top_offset($candidate) < 0) {
return candidate; return $candidate;
} }
// We cannot use .prev(".recipient_row") here, because that // We cannot use .prev(".recipient_row") here, because that
// returns nothing if the previous element is not a recipient // returns nothing if the previous element is not a recipient
// row, rather than finding the first recipient_row. // row, rather than finding the first recipient_row.
candidate = candidate.prev(); $candidate = $candidate.prev();
} }
return undefined; return undefined;
@@ -267,31 +267,31 @@ function show_floating_recipient_bar() {
} }
} }
let old_source; let $old_source;
function replace_floating_recipient_bar(source_info) { function replace_floating_recipient_bar(source_info) {
const source_recipient_bar = source_info.elem; const $source_recipient_bar = source_info.$elem;
let new_label; let $new_label;
let other_label; let $other_label;
let header; let $header;
if (source_recipient_bar !== old_source) { if ($source_recipient_bar !== $old_source) {
if (source_recipient_bar.children(".message_header_stream").length !== 0) { if ($source_recipient_bar.children(".message_header_stream").length !== 0) {
new_label = $("#current_label_stream"); $new_label = $("#current_label_stream");
other_label = $("#current_label_private_message"); $other_label = $("#current_label_private_message");
header = source_recipient_bar.children(".message_header_stream"); $header = $source_recipient_bar.children(".message_header_stream");
} else { } else {
new_label = $("#current_label_private_message"); $new_label = $("#current_label_private_message");
other_label = $("#current_label_stream"); $other_label = $("#current_label_stream");
header = source_recipient_bar.children(".message_header_private_message"); $header = $source_recipient_bar.children(".message_header_private_message");
} }
new_label.find(".message_header").replaceWith(header.clone()); $new_label.find(".message_header").replaceWith($header.clone());
other_label.css("display", "none"); $other_label.css("display", "none");
new_label.css("display", "block"); $new_label.css("display", "block");
new_label.attr("zid", rows.id(rows.first_message_in_group(source_recipient_bar))); $new_label.attr("zid", rows.id(rows.first_message_in_group($source_recipient_bar)));
new_label.toggleClass("message-fade", source_recipient_bar.hasClass("message-fade")); $new_label.toggleClass("message-fade", $source_recipient_bar.hasClass("message-fade"));
old_source = source_recipient_bar; $old_source = $source_recipient_bar;
} }
const rendered_date = source_info.date_html || ""; const rendered_date = source_info.date_html || "";
@@ -310,7 +310,7 @@ export function hide() {
export function de_clutter_dates(items) { export function de_clutter_dates(items) {
for (const item of items) { for (const item of items) {
item.elem.find(".recipient_row_date").toggle(item.show_date); item.$elem.find(".recipient_row_date").toggle(item.show_date);
} }
} }

View File

@@ -90,11 +90,11 @@ the selector and then calls browser_history.go_to_location.
const scroll_positions = new Map(); const scroll_positions = new Map();
export function update_org_settings_menu_item() { export function update_org_settings_menu_item() {
const item = $(".admin-menu-item").expectOne(); const $item = $(".admin-menu-item").expectOne();
if (page_params.is_admin) { if (page_params.is_admin) {
item.find("span").text($t({defaultMessage: "Manage organization"})); $item.find("span").text($t({defaultMessage: "Manage organization"}));
} else { } else {
item.find("span").text($t({defaultMessage: "Organization settings"})); $item.find("span").text($t({defaultMessage: "Organization settings"}));
} }
} }

View File

@@ -15,13 +15,13 @@ import * as ui_util from "./ui_util";
let giphy_fetch; let giphy_fetch;
let search_term = ""; let search_term = "";
let gifs_grid; let gifs_grid;
let active_popover_element; let $active_popover_element;
// Only used if popover called from edit message, otherwise it is `undefined`. // Only used if popover called from edit message, otherwise it is `undefined`.
let edit_message_id; let edit_message_id;
export function is_popped_from_edit_messsage() { export function is_popped_from_edit_messsage() {
return active_popover_element && edit_message_id !== undefined; return $active_popover_element && edit_message_id !== undefined;
} }
export function focus_current_edit_message() { export function focus_current_edit_message() {
@@ -102,16 +102,16 @@ async function renderGIPHYGrid(targetEl) {
// GIF; nice in principle but too distracting. // GIF; nice in principle but too distracting.
hideAttribution: true, hideAttribution: true,
onGifClick: (props) => { onGifClick: (props) => {
let textarea = $("#compose-textarea"); let $textarea = $("#compose-textarea");
if (edit_message_id !== undefined) { if (edit_message_id !== undefined) {
textarea = $( $textarea = $(
`#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`, `#edit_form_${CSS.escape(edit_message_id)} .message_edit_content`,
); );
} }
compose_ui.insert_syntax_and_focus( compose_ui.insert_syntax_and_focus(
`[](${props.images.downsized_medium.url})`, `[](${props.images.downsized_medium.url})`,
textarea, $textarea,
); );
hide_giphy_popover(); hide_giphy_popover();
}, },
@@ -146,11 +146,11 @@ async function update_grid_with_search_term() {
return; return;
} }
const search_elem = $("#giphy-search-query"); const $search_elem = $("#giphy-search-query");
// GIPHY popover may have been hidden by the // GIPHY popover may have been hidden by the
// time this function is called. // time this function is called.
if (search_elem.length) { if ($search_elem.length) {
search_term = search_elem[0].value; search_term = $search_elem[0].value;
gifs_grid.remove(); gifs_grid.remove();
gifs_grid = await renderGIPHYGrid($("#giphy_grid_in_popover .giphy-content")[0]); gifs_grid = await renderGIPHYGrid($("#giphy_grid_in_popover .giphy-content")[0]);
return; return;
@@ -162,15 +162,15 @@ async function update_grid_with_search_term() {
export function hide_giphy_popover() { export function hide_giphy_popover() {
// Returns `true` if the popover was open. // Returns `true` if the popover was open.
if (active_popover_element) { if ($active_popover_element) {
// We need to destroy the popover because when // We need to destroy the popover because when
// we hide it, bootstrap popover // we hide it, bootstrap popover
// library removes `giphy-content` element // library removes `giphy-content` element
// as part of cleaning up everything inside // as part of cleaning up everything inside
// `popover-content`, so we need to reinitialize // `popover-content`, so we need to reinitialize
// the popover by destroying it. // the popover by destroying it.
active_popover_element.popover("destroy"); $active_popover_element.popover("destroy");
active_popover_element = undefined; $active_popover_element = undefined;
edit_message_id = undefined; edit_message_id = undefined;
gifs_grid = undefined; gifs_grid = undefined;
return true; return true;
@@ -188,7 +188,7 @@ function get_popover_content() {
function get_popover_placement() { function get_popover_placement() {
let placement = popovers.compute_placement( let placement = popovers.compute_placement(
active_popover_element, $active_popover_element,
APPROX_HEIGHT, APPROX_HEIGHT,
APPROX_WIDTH, APPROX_WIDTH,
true, true,
@@ -221,7 +221,7 @@ export function initialize() {
e.stopPropagation(); e.stopPropagation();
const compose_click_target = compose_ui.get_compose_click_target(e); const compose_click_target = compose_ui.get_compose_click_target(e);
if (active_popover_element && active_popover_element.get()[0] === compose_click_target) { if ($active_popover_element && $active_popover_element.get()[0] === compose_click_target) {
// Hide giphy popover if already active. // Hide giphy popover if already active.
hide_giphy_popover(); hide_giphy_popover();
return; return;
@@ -237,8 +237,8 @@ export function initialize() {
edit_message_id = undefined; edit_message_id = undefined;
} }
active_popover_element = $elt; $active_popover_element = $elt;
active_popover_element.popover({ $active_popover_element.popover({
animation: true, animation: true,
placement: get_popover_placement(), placement: get_popover_placement(),
html: true, html: true,
@@ -250,7 +250,7 @@ export function initialize() {
content: " ", content: " ",
}); });
active_popover_element.popover("show"); $active_popover_element.popover("show");
// It takes about 1s for the popover to show; So, // It takes about 1s for the popover to show; So,
// we wait for popover to display before rendering GIFs // we wait for popover to display before rendering GIFs
// in it, otherwise popover is rendered with empty content. // in it, otherwise popover is rendered with empty content.

View File

@@ -476,20 +476,20 @@ export function process_tab_key() {
// TODO: See if browsers like Safari can now handle tabbing correctly // TODO: See if browsers like Safari can now handle tabbing correctly
// without our intervention. // without our intervention.
let message_edit_form; let $message_edit_form;
const focused_message_edit_content = $(".message_edit_content:focus"); const $focused_message_edit_content = $(".message_edit_content:focus");
if (focused_message_edit_content.length > 0) { if ($focused_message_edit_content.length > 0) {
message_edit_form = focused_message_edit_content.closest(".message_edit_form"); $message_edit_form = $focused_message_edit_content.closest(".message_edit_form");
// Open message edit forms either have a save button or a close button, but not both. // Open message edit forms either have a save button or a close button, but not both.
message_edit_form.find(".message_edit_save,.message_edit_close").trigger("focus"); $message_edit_form.find(".message_edit_save,.message_edit_close").trigger("focus");
return true; return true;
} }
const focused_message_edit_save = $(".message_edit_save:focus"); const $focused_message_edit_save = $(".message_edit_save:focus");
if (focused_message_edit_save.length > 0) { if ($focused_message_edit_save.length > 0) {
message_edit_form = focused_message_edit_save.closest(".message_edit_form"); $message_edit_form = $focused_message_edit_save.closest(".message_edit_form");
message_edit_form.find(".message_edit_cancel").trigger("focus"); $message_edit_form.find(".message_edit_cancel").trigger("focus");
return true; return true;
} }
@@ -519,9 +519,9 @@ export function process_shift_tab_key() {
} }
// Shift-Tabbing from the edit message save button takes you to the content. // Shift-Tabbing from the edit message save button takes you to the content.
const focused_message_edit_save = $(".message_edit_save:focus"); const $focused_message_edit_save = $(".message_edit_save:focus");
if (focused_message_edit_save.length > 0) { if ($focused_message_edit_save.length > 0) {
focused_message_edit_save $focused_message_edit_save
.closest(".message_edit_form") .closest(".message_edit_form")
.find(".message_edit_content") .find(".message_edit_content")
.trigger("focus"); .trigger("focus");
@@ -925,8 +925,8 @@ export function process_hotkey(e, hotkey) {
compose_actions.quote_and_reply({trigger: "hotkey"}); compose_actions.quote_and_reply({trigger: "hotkey"});
return true; return true;
case "edit_message": { case "edit_message": {
const row = message_lists.current.get_row(msg.id); const $row = message_lists.current.get_row(msg.id);
message_edit.start(row); message_edit.start($row);
return true; return true;
} }
} }

View File

@@ -69,30 +69,30 @@ export function post_hotspot_as_read(hotspot_name) {
} }
function place_icon(hotspot) { function place_icon(hotspot) {
const element = $(hotspot.location.element); const $element = $(hotspot.location.element);
const icon = $(`#hotspot_${CSS.escape(hotspot.name)}_icon`); const $icon = $(`#hotspot_${CSS.escape(hotspot.name)}_icon`);
if ( if (
element.length === 0 || $element.length === 0 ||
element.css("display") === "none" || $element.css("display") === "none" ||
!element.is(":visible") || !$element.is(":visible") ||
element.is(":hidden") $element.is(":hidden")
) { ) {
icon.css("display", "none"); $icon.css("display", "none");
return false; return false;
} }
const offset = { const offset = {
top: element.outerHeight() * hotspot.location.offset_y, top: $element.outerHeight() * hotspot.location.offset_y,
left: element.outerWidth() * hotspot.location.offset_x, left: $element.outerWidth() * hotspot.location.offset_x,
}; };
const client_rect = element.get(0).getBoundingClientRect(); const client_rect = $element.get(0).getBoundingClientRect();
const placement = { const placement = {
top: client_rect.top + offset.top, top: client_rect.top + offset.top,
left: client_rect.left + offset.left, left: client_rect.left + offset.left,
}; };
icon.css("display", "block"); $icon.css("display", "block");
icon.css(placement); $icon.css(placement);
return true; return true;
} }

View File

@@ -189,19 +189,19 @@ export function set_up_toggler() {
}; };
toggler = components.toggle(opts); toggler = components.toggle(opts);
const elem = toggler.get(); const $elem = toggler.get();
elem.addClass("large allow-overflow"); $elem.addClass("large allow-overflow");
const modals = opts.values.map((item) => { const modals = opts.values.map((item) => {
const key = item.key; // e.g. message-formatting const key = item.key; // e.g. message-formatting
const modal = $(`#${CSS.escape(key)}`).find(".modal-body"); const $modal = $(`#${CSS.escape(key)}`).find(".modal-body");
return modal; return $modal;
}); });
for (const modal of modals) { for (const $modal of modals) {
ui.get_scroll_element(modal).prop("tabindex", 0); ui.get_scroll_element($modal).prop("tabindex", 0);
keydown_util.handle({ keydown_util.handle({
elem: modal, $elem: $modal,
handlers: { handlers: {
ArrowLeft: toggler.maybe_go_left, ArrowLeft: toggler.maybe_go_left,
ArrowRight: toggler.maybe_go_right, ArrowRight: toggler.maybe_go_right,
@@ -209,7 +209,7 @@ export function set_up_toggler() {
}); });
} }
$(".informational-overlays .overlay-tabs").append(elem); $(".informational-overlays .overlay-tabs").append($elem);
$("#go-to-default-view-hotkey-help").toggleClass( $("#go-to-default-view-hotkey-help").toggleClass(
"notdisplayed", "notdisplayed",
@@ -224,12 +224,12 @@ export function show(target) {
set_up_toggler(); set_up_toggler();
} }
const overlay = $(".informational-overlays"); const $overlay = $(".informational-overlays");
if (!overlay.hasClass("show")) { if (!$overlay.hasClass("show")) {
overlays.open_overlay({ overlays.open_overlay({
name: "informationalOverlays", name: "informationalOverlays",
overlay, $overlay,
on_close() { on_close() {
browser_history.exit_overlay(); browser_history.exit_overlay();
}, },

View File

@@ -14,7 +14,7 @@ export function random_id() {
} }
export function create(opts) { export function create(opts) {
if (!opts.container) { if (!opts.$container) {
blueslip.error("Pill needs container."); blueslip.error("Pill needs container.");
return undefined; return undefined;
} }
@@ -34,8 +34,8 @@ export function create(opts) {
const store = { const store = {
pills: [], pills: [],
pill_config: opts.pill_config, pill_config: opts.pill_config,
$parent: opts.container, $parent: opts.$container,
$input: opts.container.find(".input").expectOne(), $input: opts.$container.find(".input").expectOne(),
create_item_from_text: opts.create_item_from_text, create_item_from_text: opts.create_item_from_text,
get_text_from_item: opts.get_text_from_item, get_text_from_item: opts.get_text_from_item,
}; };

View File

@@ -71,9 +71,9 @@ function beforeSend() {
} }
function submit_invitation_form() { function submit_invitation_form() {
const invite_status = $("#invite_status"); const $invite_status = $("#invite_status");
const invitee_emails = $("#invitee_emails"); const $invitee_emails = $("#invitee_emails");
const invitee_emails_group = invitee_emails.closest(".control-group"); const $invitee_emails_group = $invitee_emails.closest(".control-group");
const data = get_common_invitation_data(); const data = get_common_invitation_data();
data.invitee_emails = $("#invitee_emails").val(); data.invitee_emails = $("#invitee_emails").val();
@@ -84,10 +84,10 @@ function submit_invitation_form() {
success() { success() {
ui_report.success( ui_report.success(
$t_html({defaultMessage: "User(s) invited successfully."}), $t_html({defaultMessage: "User(s) invited successfully."}),
invite_status, $invite_status,
); );
invitee_emails_group.removeClass("warning"); $invitee_emails_group.removeClass("warning");
invitee_emails.val(""); $invitee_emails.val("");
if (page_params.development_environment) { if (page_params.development_environment) {
const rendered_email_msg = render_settings_dev_env_email_access(); const rendered_email_msg = render_settings_dev_env_email_access();
@@ -98,7 +98,7 @@ function submit_invitation_form() {
const arr = JSON.parse(xhr.responseText); const arr = JSON.parse(xhr.responseText);
if (arr.errors === undefined) { if (arr.errors === undefined) {
// There was a fatal error, no partial processing occurred. // There was a fatal error, no partial processing occurred.
ui_report.error("", xhr, invite_status); ui_report.error("", xhr, $invite_status);
} else { } else {
// Some users were not invited. // Some users were not invited.
const invitee_emails_errored = []; const invitee_emails_errored = [];
@@ -122,11 +122,11 @@ function submit_invitation_form() {
has_billing_access: page_params.is_owner || page_params.is_billing_admin, has_billing_access: page_params.is_owner || page_params.is_billing_admin,
daily_limit_reached: arr.daily_limit_reached, daily_limit_reached: arr.daily_limit_reached,
}); });
ui_report.message(error_response, invite_status, "alert-warning"); ui_report.message(error_response, $invite_status, "alert-warning");
invitee_emails_group.addClass("warning"); $invitee_emails_group.addClass("warning");
if (arr.sent_invitations) { if (arr.sent_invitations) {
invitee_emails.val(invitee_emails_errored.join("\n")); $invitee_emails.val(invitee_emails_errored.join("\n"));
} }
} }
}, },
@@ -140,7 +140,7 @@ function submit_invitation_form() {
} }
function generate_multiuse_invite() { function generate_multiuse_invite() {
const invite_status = $("#multiuse_invite_status"); const $invite_status = $("#multiuse_invite_status");
const data = get_common_invitation_data(); const data = get_common_invitation_data();
channel.post({ channel.post({
url: "/json/invites/multiuse", url: "/json/invites/multiuse",
@@ -148,11 +148,11 @@ function generate_multiuse_invite() {
beforeSend, beforeSend,
success(data) { success(data) {
const copy_link_html = copy_invite_link(data); const copy_link_html = copy_invite_link(data);
ui_report.success(copy_link_html, invite_status); ui_report.success(copy_link_html, $invite_status);
new ClipboardJS("#copy_generated_invite_link"); new ClipboardJS("#copy_generated_invite_link");
}, },
error(xhr) { error(xhr) {
ui_report.error("", xhr, invite_status); ui_report.error("", xhr, $invite_status);
}, },
complete() { complete() {
$("#submit-invitation").text($t({defaultMessage: "Generate invite link"})); $("#submit-invitation").text($t({defaultMessage: "Generate invite link"}));
@@ -187,7 +187,7 @@ export function launch() {
overlays.open_overlay({ overlays.open_overlay({
name: "invite", name: "invite",
overlay: $("#invite-user"), $overlay: $("#invite-user"),
on_close() { on_close() {
browser_history.exit_overlay(); browser_history.exit_overlay();
}, },

View File

@@ -8,12 +8,12 @@ export const vim_up = "k";
export const vim_right = "l"; export const vim_right = "l";
export function handle(opts: { export function handle(opts: {
elem: JQuery; $elem: JQuery;
handlers: { handlers: {
[handler: string]: (() => boolean) | undefined; [handler: string]: (() => boolean) | undefined;
}; };
}): void { }): void {
opts.elem.on("keydown", (e) => { opts.$elem.on("keydown", (e) => {
if (e.altKey || e.ctrlKey || e.shiftKey) { if (e.altKey || e.ctrlKey || e.shiftKey) {
return; return;
} }

View File

@@ -183,12 +183,12 @@ export function render_lightbox_list_images(preview_source) {
const src = img.getAttribute("src"); const src = img.getAttribute("src");
const className = preview_source === src ? "image selected" : "image"; const className = preview_source === src ? "image selected" : "image";
const node = $("<div></div>", { const $node = $("<div></div>", {
class: className, class: className,
"data-src": src, "data-src": src,
}).css({backgroundImage: "url(" + src + ")"}); }).css({backgroundImage: "url(" + src + ")"});
$image_list.append(node); $image_list.append($node);
// We parse the data for each image to show in the list, // We parse the data for each image to show in the list,
// while we still have its original DOM element handy, so // while we still have its original DOM element handy, so
@@ -205,10 +205,10 @@ function display_image(payload) {
$(".player-container").hide(); $(".player-container").hide();
$(".image-preview, .image-actions, .image-description, .download, .lightbox-zoom-reset").show(); $(".image-preview, .image-actions, .image-description, .download, .lightbox-zoom-reset").show();
const img_container = $("#lightbox_overlay .image-preview > .zoom-element"); const $img_container = $("#lightbox_overlay .image-preview > .zoom-element");
const img = new Image(); const img = new Image();
img.src = payload.source; img.src = payload.source;
img_container.html(img).show(); $img_container.html(img).show();
$(".image-description .title") $(".image-description .title")
.text(payload.title || "N/A") .text(payload.title || "N/A")
@@ -244,16 +244,16 @@ function display_video(payload) {
break; break;
} }
const iframe = $("<iframe></iframe>"); const $iframe = $("<iframe></iframe>");
iframe.attr( $iframe.attr(
"sandbox", "sandbox",
"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts", "allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts",
); );
iframe.attr("src", source); $iframe.attr("src", source);
iframe.attr("frameborder", 0); $iframe.attr("frameborder", 0);
iframe.attr("allowfullscreen", true); $iframe.attr("allowfullscreen", true);
$("#lightbox_overlay .player-container").html(iframe).show(); $("#lightbox_overlay .player-container").html($iframe).show();
$(".image-actions .open").attr("href", payload.url); $(".image-actions .open").attr("href", payload.url);
} }
@@ -303,7 +303,7 @@ export function build_open_image_function(on_close) {
overlays.open_overlay({ overlays.open_overlay({
name: "lightbox", name: "lightbox",
overlay: $("#lightbox_overlay"), $overlay: $("#lightbox_overlay"),
on_close, on_close,
}); });
@@ -359,11 +359,11 @@ export function show_from_selected_message() {
// retrieve the metadata from the DOM and store into the asset_map. // retrieve the metadata from the DOM and store into the asset_map.
export function parse_image_data(image) { export function parse_image_data(image) {
const $image = $(image); const $image = $(image);
const $preview_src = $image.attr("src"); const preview_src = $image.attr("src");
if (asset_map.has($preview_src)) { if (asset_map.has(preview_src)) {
// check if image's data is already present in asset_map. // check if image's data is already present in asset_map.
return asset_map.get($preview_src); return asset_map.get(preview_src);
} }
// if wrapped in the .youtube-video class, it will be length = 1, and therefore // if wrapped in the .youtube-video class, it will be length = 1, and therefore
@@ -376,24 +376,24 @@ export function parse_image_data(image) {
const is_compose_preview_image = $image.closest("#compose .preview_content").length === 1; const is_compose_preview_image = $image.closest("#compose .preview_content").length === 1;
const $parent = $image.parent(); const $parent = $image.parent();
let $type; let type;
let $source; let source;
const $url = $parent.attr("href"); const url = $parent.attr("href");
if (is_youtube_video) { if (is_youtube_video) {
$type = "youtube-video"; type = "youtube-video";
$source = $parent.attr("data-id"); source = $parent.attr("data-id");
} else if (is_vimeo_video) { } else if (is_vimeo_video) {
$type = "vimeo-video"; type = "vimeo-video";
$source = $parent.attr("data-id"); source = $parent.attr("data-id");
} else if (is_embed_video) { } else if (is_embed_video) {
$type = "embed-video"; type = "embed-video";
$source = $parent.attr("data-id"); source = $parent.attr("data-id");
} else { } else {
$type = "image"; type = "image";
if ($image.attr("data-src-fullsize")) { if ($image.attr("data-src-fullsize")) {
$source = $image.attr("data-src-fullsize"); source = $image.attr("data-src-fullsize");
} else { } else {
$source = $preview_src; source = preview_src;
} }
} }
let sender_full_name; let sender_full_name;
@@ -412,13 +412,13 @@ export function parse_image_data(image) {
const payload = { const payload = {
user: sender_full_name, user: sender_full_name,
title: $parent.attr("title"), title: $parent.attr("title"),
type: $type, type,
preview: $preview_src, preview: preview_src,
source: $source, source,
url: $url, url,
}; };
asset_map.set($preview_src, payload); asset_map.set(preview_src, payload);
return payload; return payload;
} }

Some files were not shown because too many files have changed in this diff Show More