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;
}