diff --git a/templates/zephyr/home.html b/templates/zephyr/home.html index ff2649e4fa..7d76678d1d 100644 --- a/templates/zephyr/home.html +++ b/templates/zephyr/home.html @@ -97,4 +97,6 @@ -
More messages below
+
+
+
diff --git a/zephyr/static/js/notifications_bar.js b/zephyr/static/js/notifications_bar.js index 9988fc86c8..5d40089d67 100644 --- a/zephyr/static/js/notifications_bar.js +++ b/zephyr/static/js/notifications_bar.js @@ -2,33 +2,92 @@ var notifications_bar = (function () { var exports = {}; -var disabled = false; +var disabled = false; // true when the bar should be hidden (eg, it's blocking the composebox) +var displayed = false; // true when the bar is supposedly displayed (ignoring disabled-ness) +var on_custom = false; // true when the bar is showing a custom message +var custom_message = ""; // the current custom message being displayed, if any +var current_message = ""; // the current notification being displayed in the bar, if any +var timeoutID = null; // keeping track of the clear_custom_message timer, so we can cancel it +var bar_selector = "#notifications-bar"; // the selector jQuery can use to pick the notifications bar +var area_selector = "#notifications-area"; // the selector jQuery can use to pick the container -function show() { - $('.notifications').slideDown(50); +// Try to show msg (but this might fail if the bar is disabled) +function show(msg) { + if (disabled) + return; // we should never show the bar when disabled + + if (displayed && msg !== current_message) { + // If the bar is already displayed and we're changing the text, show an animation + var changeText = function () { + // Custom effect to put change of text in the queue (after slideUp) + $(this).text(msg); + $(this).dequeue(); + }; + $(bar_selector).slideUp(50).queue(changeText).delay(100).slideDown(50); + } else if (!displayed) { + // If the bar wasn't already displayed, simply show it + $(bar_selector).text(msg).slideDown(50); + displayed = true; // we need to set this flag + } + // In the last case (the bar is already displayed and has the right text), do nothing + + // We can't use $(bar_selector).text() to get the current notification + // because, in one of the cases above, the text isn't actually changed + // immediately. Instead, let's store the current notification in a global + // variable. + current_message = msg; } +// Hide the notifications bar function hide() { - $('.notifications').slideUp(50); + if (!displayed) + return; // don't unnecessarily add to the element's fx queue + displayed = false; + current_message = ""; + $(bar_selector).slideUp(50); } +// If there's a custom message, or if the last message is off the bottom of the +// screen, then show the notifications bar. exports.update = function () { - if (rows.last_visible().offset() === null) - return; - if (rows.last_visible().offset().top + rows.last_visible().height() > viewport.scrollTop() + viewport.height() && !disabled) - show(); + if (on_custom) + show(custom_message); + else if (rows.last_visible().offset() !== null // otherwise the next line will error + && rows.last_visible().offset().top + rows.last_visible().height() > viewport.scrollTop() + viewport.height()) + show("More messages below"); else hide(); }; +// Clear the custom message and go back to the default (called by a timer) +function clear_custom_message() { + on_custom = false; + custom_message = ""; + timeoutID = null; + exports.update(); +} + +// Show the message msg for duration milliseconds. If the notifications bar is +// hidden by the composebox, the timer still ticks. Also, if this method is +// called again, the new message will overwrite the old one. +exports.show_custom_message = function (msg, duration) { + if (timeoutID !== null) + window.clearTimeout(timeoutID); // clear any existing timers + on_custom = true; + custom_message = msg; + show(msg); + timeoutID = window.setTimeout(clear_custom_message, duration); +}; + // We disable the notifications bar if it overlaps with the composebox exports.maybe_disable = function() { - if ($("#compose").offset().left + $("#compose").width() > $(".notifications").offset().left) { + if ($("#compose").offset().left + $("#compose").width() > $(area_selector).offset().left) { disabled = true; - exports.update(); + hide(); } }; +// Un-disable the notifications bar, then call the update function to see if it should be displayed exports.enable = function() { disabled = false; exports.update(); diff --git a/zephyr/static/styles/zephyr.css b/zephyr/static/styles/zephyr.css index 3a5f9f5fff..15f6d7603a 100644 --- a/zephyr/static/styles/zephyr.css +++ b/zephyr/static/styles/zephyr.css @@ -773,13 +773,20 @@ table.floating_recipient { margin-bottom: 5px; } -.notifications { +#notifications-area { position: fixed; z-index: 9000; bottom: 0px; right: 20px; width: 200px; - height: 30px; + height: 35px; +} + +#notifications-bar { + position: absolute; + bottom: 0px; /* necessary to get slideUp, slideDown directions correct */ + width: 100%; + height: 100%; border-radius: 10px 10px 0px 0px; padding: 10px 0px 0px 10px; background: #58F; @@ -787,4 +794,8 @@ table.floating_recipient { font-size: 125%; cursor: default; display: none; + /* For now, cut off long messages (but we should find a better solution) */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; }