var ui = (function () { var exports = {}; var actively_scrolling = false; exports.have_scrolled_away_from_top = true; exports.actively_scrolling = function () { return actively_scrolling; }; // What, if anything, obscures the home tab? exports.replace_emoji_with_text = function (element) { element.find(".emoji").replaceWith(function () { return $(this).attr("alt"); }); }; /* Arguments used in the report_* functions are, response- response that we want to display status_box- element being used to display the response cls- class that we want to add/remove to/from the status_box type- used to define more complex logic for special cases (currently being used only for subscriptions-status) */ exports.report_message = function (response, status_box, cls, type) { if (cls === undefined) { cls = 'alert'; } if (type === undefined) { type = ' '; } if (type === 'subscriptions-status') { status_box.removeClass(status_classes).addClass(cls).children('#response') .text(response).stop(true).fadeTo(0, 1); } else { status_box.removeClass(status_classes).addClass(cls) .text(response).stop(true).fadeTo(0, 1); } status_box.show(); }; exports.report_error = function (response, xhr, status_box, type) { if (xhr && xhr.status.toString().charAt(0) === "4") { // Only display the error response for 4XX, where we've crafted // a nice response. response += ": " + JSON.parse(xhr.responseText).msg; } ui_report.message(response, status_box, 'alert-error', type); }; exports.report_success = function (response, status_box, type) { ui_report.message(response, status_box, 'alert-success', type); }; function update_message_in_all_views(message_id, callback) { _.each([message_list.all, home_msg_list, message_list.narrowed], function (list) { if (list === undefined) { return; } var row = list.get_row(message_id); if (row === undefined) { // The row may not exist, e.g. if you do an action on a message in // a narrowed view return; } callback(row); }); } exports.find_message = function (message_id) { // Try to find the message object. It might be in the narrow list // (if it was loaded when narrowed), or only in the message_list.all // (if received from the server while in a different narrow) var message; _.each([message_list.all, home_msg_list, message_list.narrowed], function (msg_list) { if (msg_list !== undefined && message === undefined) { message = msg_list.get(message_id); } }); return message; }; exports.update_starred = function (message_id, starred) { // Update the message object pointed to by the various message // lists. var message = exports.find_message(message_id); // If it isn't cached in the browser, no need to do anything if (message === undefined) { return; } unread_ops.mark_message_as_read(message); message.starred = starred; // Avoid a full re-render, but update the star in each message // table in which it is visible. update_message_in_all_views(message_id, function update_row(row) { var elt = row.find(".star"); if (starred) { elt.addClass("icon-vector-star").removeClass("icon-vector-star-empty").removeClass("empty-star"); } else { elt.removeClass("icon-vector-star").addClass("icon-vector-star-empty").addClass("empty-star"); } var title_state = message.starred ? "Unstar" : "Star"; elt.attr("title", title_state + " this message"); }); }; var local_messages_to_show = []; var show_message_timestamps = _.throttle(function () { _.each(local_messages_to_show, function (message_id) { update_message_in_all_views(message_id, function update_row(row) { row.find('.message_time').toggleClass('notvisible', false); }); }); local_messages_to_show = []; }, 100); exports.show_local_message_arrived = function (message_id) { local_messages_to_show.push(message_id); show_message_timestamps(); }; exports.show_message_failed = function (message_id, failed_msg) { // Failed to send message, so display inline retry/cancel update_message_in_all_views(message_id, function update_row(row) { var failed_div = row.find('.message_failed'); failed_div.toggleClass('notvisible', false); failed_div.find('.failed_text').attr('title', failed_msg); }); }; exports.show_failed_message_success = function (message_id) { // Previously failed message succeeded update_message_in_all_views(message_id, function update_row(row) { row.find('.message_failed').toggleClass('notvisible', true); }); }; $(document).ready(function () { var info_overlay_toggle = components.toggle({ name: "info-overlay-toggle", selected: 0, values: [ { label: "Keyboard shortcuts", key: "keyboard-shortcuts" }, { label: "Message formatting", key: "markdown-help" }, { label: "Search operators", key: "search-operators" }, ], callback: function (name, key) { $(".overlay-modal").hide(); $("#" + key).show(); }, }).get(); $(".informational-overlays .overlay-tabs") .append($(info_overlay_toggle).addClass("large")); }); exports.show_info_overlay = function (target) { var el = { overlay: $(".informational-overlays"), }; if (!el.overlay.hasClass("show")) { $(el.overlay).addClass("show"); } if (target) { components.toggle.lookup("info-overlay-toggle").goto(target); } }; var loading_more_messages_indicator_showing = false; exports.show_loading_more_messages_indicator = function () { if (! loading_more_messages_indicator_showing) { loading.make_indicator($('#loading_more_messages_indicator'), {abs_positioned: true}); loading_more_messages_indicator_showing = true; floating_recipient_bar.hide(); } }; exports.hide_loading_more_messages_indicator = function () { if (loading_more_messages_indicator_showing) { loading.destroy_indicator($("#loading_more_messages_indicator")); loading_more_messages_indicator_showing = false; } }; /* EXPERIMENTS */ /* This method allows an advanced user to use the console * to switch the application to span full width of the browser. */ exports.switchToFullWidth = function () { $("#full-width-style").remove(); $('head').append(''); return ("Switched to full width"); }; /* END OF EXPERIMENTS */ function scroll_finished() { actively_scrolling = false; if ($('#home').hasClass('active')) { if (!pointer.suppress_scroll_pointer_update) { message_viewport.keep_pointer_in_view(); } else { pointer.suppress_scroll_pointer_update = false; } floating_recipient_bar.update(); if (message_viewport.scrollTop() === 0 && ui.have_scrolled_away_from_top) { ui.have_scrolled_away_from_top = false; message_fetch.load_more_messages(current_msg_list); } else if (!ui.have_scrolled_away_from_top) { ui.have_scrolled_away_from_top = true; } // When the window scrolls, it may cause some messages to // enter the screen and become read. Calling // unread_ops.process_visible will update necessary // data structures and DOM elements. setTimeout(unread_ops.process_visible, 0); } } var scroll_timer; function scroll_finish() { actively_scrolling = true; clearTimeout(scroll_timer); scroll_timer = setTimeout(scroll_finished, 100); } // Save the compose content cursor position and restore when we // shift-tab back in (see hotkey.js). var saved_compose_cursor = 0; $(function () { message_viewport.message_pane.scroll($.throttle(50, function () { unread_ops.process_visible(); scroll_finish(); })); $('#new_message_content').blur(function () { saved_compose_cursor = $(this).caret(); }); }); exports.restore_compose_cursor = function () { $('#new_message_content') .focus() .caret(saved_compose_cursor); }; $(function () { if (window.bridge !== undefined) { // Disable "spellchecking" in our desktop app. The "spellchecking" // in our Mac app is actually autocorrect, and frustrates our // users. $("#new_message_content").attr('spellcheck', 'false'); // Modify the zephyr mirroring error message in our desktop // app, since it doesn't work from the desktop version. $("#webathena_login_menu").hide(); $("#normal-zephyr-mirror-error-text").addClass("notdisplayed"); $("#desktop-zephyr-mirror-error-text").removeClass("notdisplayed"); } }); return exports; }()); if (typeof module !== 'undefined') { module.exports = ui; }