Module pattern for ui.js

(imported from commit 951984ec1006e93a0ffc7e299b52fa02c10eb976)
This commit is contained in:
Zev Benjamin 2012-11-16 10:45:39 -05:00
parent da6cc30134
commit 90e0fc6259
10 changed files with 87 additions and 79 deletions

View File

@ -121,8 +121,8 @@
<div class="message_content">
<textarea class="new_message_textarea" name="content" id="new_message_content"
value="" placeholder="Compose your message here..." tabindex="140"></textarea>
<div tabindex="148" onfocus="safari_composebox_hack(true);"></div>
<div tabindex="149" onfocus="safari_composebox_hack(false);"></div>
<div tabindex="148" onfocus="ui.safari_composebox_hack(true);"></div>
<div tabindex="149" onfocus="ui.safari_composebox_hack(false);"></div>
<input type="submit" value="Send" id="compose-send-button" class="btn send_message" tabindex="150"/>
</div>
</td>

View File

@ -8,7 +8,7 @@
<div id="API">
<label>API Key</label>
<div id="api_key_button_box">
<a href="#api-settings" id="api_key_button" onclick="show_api_key_box();">(show)</a>
<a href="#api-settings" id="api_key_button" onclick="ui.show_api_key_box();">(show)</a>
<br />
</div>
<div id="get_api_key_box">
@ -26,7 +26,7 @@
<div id="Photo">
<label>Photo</label>
<img class="img-rounded gravatar-profile" src="https://secure.gravatar.com/avatar/{{ email_hash }}?d=identicon&s=80"/>
<a href="https://en.gravatar.com/emails" target="_blank" onclick="wait_for_gravatar();">(change at Gravatar.com)</a>
<a href="https://en.gravatar.com/emails" target="_blank" onclick="ui.wait_for_gravatar();">(change at Gravatar.com)</a>
<br />
</div>
<br /><br />

View File

@ -42,10 +42,7 @@ var globals =
+ ' typeahead_helper'
// ui.js
+ ' register_onclick hide_email show_email focus_on'
+ ' report_error report_success report_message clicking mouse_moved'
+ ' userinfo_currently_popped hide_userinfo_popover update_gravatars'
+ ' gravatar_stamp register_user_info_mouseover register_user_info_mouseout'
+ ' ui'
// zephyr.js
+ ' message_array message_dict get_updates_params'

View File

@ -225,7 +225,7 @@ function check_stream_for_send(stream_name) {
},
error: function (xhr) {
result = "error";
report_error("Error checking subscription", xhr, $("#home-error"));
ui.report_error("Error checking subscription", xhr, $("#home-error"));
$("#stream").focus();
$("#compose-send-button").removeAttr('disabled');
}

View File

@ -96,7 +96,7 @@ function handle_keyup(e) {
var code = e.keyCode || e.which;
if (code === 13 || (code === 9 && !e.shiftKey)) { // Enter key or tab key
if (nextFocus) {
focus_on(nextFocus);
ui.focus_on(nextFocus);
nextFocus = false;
}
}

View File

@ -78,8 +78,8 @@ function process_hotkey(e) {
}
return false;
case 27: // Esc: close userinfo popup, cancel compose, or un-narrow
if (userinfo_currently_popped()) {
hide_userinfo_popover();
if (ui.userinfo_currently_popped()) {
ui.hide_userinfo_popover();
} else if (compose.composing()) {
compose.cancel();
} else {

View File

@ -74,7 +74,7 @@ function do_reload_app(send_after_reload) {
preserve_compose(send_after_reload);
}
// TODO: We need a better API for showing messages.
report_message("The application has been updated; reloading!", $("#reloading-application"));
ui.report_message("The application has been updated; reloading!", $("#reloading-application"));
reload_in_progress = true;
window.location.reload(true);
}

View File

@ -60,7 +60,7 @@ exports.fetch = function () {
$('#streams').focus().select();
},
error: function (xhr) {
report_error("Error listing subscriptions", xhr, $("#subscriptions-status"));
ui.report_error("Error listing subscriptions", xhr, $("#subscriptions-status"));
}
});
};
@ -78,7 +78,7 @@ exports.subscribe_for_send = function (stream, prompt_button) {
prompt_button.stop(true).fadeOut(500);
},
error: function (xhr, error_type, exn) {
report_error("Unable to subscribe", xhr, $("#home-error"));
ui.report_error("Unable to subscribe", xhr, $("#home-error"));
}
});
};
@ -100,17 +100,17 @@ function ajaxSubscribe(stream) {
var name, res = $.parseJSON(xhr.responseText);
if (res.subscribed.length === 0) {
name = res.already_subscribed[0];
report_success("Already subscribed to " + name, $("#subscriptions-status"));
ui.report_success("Already subscribed to " + name, $("#subscriptions-status"));
} else {
name = res.subscribed[0];
report_success("Successfully added subscription to " + name,
ui.report_success("Successfully added subscription to " + name,
$("#subscriptions-status"));
}
add_to_stream_list(name);
$("#streams").focus();
},
error: function (xhr) {
report_error("Error adding subscription", xhr, $("#subscriptions-status"));
ui.report_error("Error adding subscription", xhr, $("#subscriptions-status"));
$("#streams").focus();
}
});
@ -126,11 +126,11 @@ exports.unsubscribe = function (stream) {
var name, res = $.parseJSON(xhr.responseText);
if (res.removed.length === 0) {
name = res.not_subscribed[0];
report_success("Already not subscribed to " + name,
ui.report_success("Already not subscribed to " + name,
$("#subscriptions-status"));
} else {
name = res.removed[0];
report_success("Successfully removed subscription to " + name,
ui.report_success("Successfully removed subscription to " + name,
$("#subscriptions-status"));
}
$('#subscriptions_table').find('button[value="' + name + '"]').text("Subscribe")
@ -146,7 +146,7 @@ exports.unsubscribe = function (stream) {
$("#streams").focus();
},
error: function (xhr) {
report_error("Error removing subscription", xhr, $("#subscriptions-status"));
ui.report_error("Error removing subscription", xhr, $("#subscriptions-status"));
$("#streams").focus();
}
});

View File

@ -1,3 +1,7 @@
var ui = (function () {
var exports = {};
// We want to remember how far we were scrolled on each 'tab'.
// To do so, we need to save away the old position of the
// scrollbar when we switch to a new tab (and restore it
@ -5,7 +9,7 @@
var scroll_positions = {};
var gravatar_stamp = 1;
function focus_on(field_id) {
exports.focus_on = function (field_id) {
// Call after autocompleting on a field, to advance the focus to
// the next input field.
@ -13,7 +17,7 @@ function focus_on(field_id) {
// autocomplete selection has been made, so we have to do this
// manually.
$("#" + field_id).focus();
}
};
/* We use 'visibility' rather than 'display' and jQuery's show() / hide(),
because we want to reserve space for the email address. This avoids
@ -31,28 +35,28 @@ function show_email(message_row) {
message_row.find('.sender_email').removeClass('invisible');
}
function report_message(response, status_box, cls) {
exports.report_message = function (response, status_box, cls) {
if (cls === undefined)
cls = 'alert';
status_box.removeClass(status_classes).addClass(cls)
.text(response).stop(true).fadeTo(0, 1);
status_box.show();
}
};
function report_error(response, xhr, status_box) {
exports.report_error = function (response, xhr, status_box) {
if (xhr.status.toString().charAt(0) === "4") {
// Only display the error response for 4XX, where we've crafted
// a nice response.
response += ": " + $.parseJSON(xhr.responseText).msg;
}
report_message(response, status_box, 'alert-error');
}
ui.report_message(response, status_box, 'alert-error');
};
function report_success(response, status_box) {
report_message(response, status_box, 'alert-success');
}
exports.report_success = function (response, status_box) {
ui.report_message(response, status_box, 'alert-success');
};
var clicking = false;
var mouse_moved = false;
@ -211,10 +215,10 @@ function hack_for_floating_recipient_bar() {
floating_recipient.offset(offset);
}
function show_api_key_box() {
exports.show_api_key_box = function () {
$("#get_api_key_box").show();
$("#api_key_button_box").hide();
}
};
var current_userinfo_popover_elem;
function show_userinfo_popover(element, id) {
@ -232,18 +236,18 @@ function show_userinfo_popover(element, id) {
}
}
function hide_userinfo_popover() {
if (userinfo_currently_popped()) {
exports.hide_userinfo_popover = function () {
if (ui.userinfo_currently_popped()) {
current_userinfo_popover_elem.popover("destroy");
current_userinfo_popover_elem = undefined;
}
}
};
function userinfo_currently_popped() {
exports.userinfo_currently_popped = function () {
return current_userinfo_popover_elem !== undefined;
}
};
function safari_composebox_hack(forwards) {
exports.safari_composebox_hack = function (forwards) {
// OK, so the situation here is basically a lot of work so that
// Tab-Enter is a valid hotkey for sending a message in Safari.
// By default, Safari uses Tab only to cycle through textboxes,
@ -264,8 +268,50 @@ function safari_composebox_hack(forwards) {
} else {
$('#new_message_content').focus();
}
};
function update_gravatars() {
$.each($(".gravatar-profile"), function(index, profile) {
$(this).attr('src', $(this).attr('src') + '?stamp=' + gravatar_stamp);
});
gravatar_stamp += 1;
}
function poll_for_gravatar_update(start_time, url) {
var updated = false;
$.ajax({
type: "HEAD",
url: url,
async: false,
cache: false,
success: function (resp, statusText, xhr) {
if (new Date(xhr.getResponseHeader('Last-Modified')) > start_time) {
update_gravatars();
updated = true;
}
}
});
// Give users 5 minutes to update their picture on gravatar.com,
// during which we try to auto-update their image on our site. If
// they take longer than that, we'll update when they press the
// save button.
if (!updated && (($.now() - start_time) < 1000 * 60 * 5)) {
setTimeout(function() {
poll_for_gravatar_update(start_time, url);
}, 1500);
}
}
exports.get_gravatar_stamp = function () {
return gravatar_stamp;
};
exports.wait_for_gravatar = function () {
poll_for_gravatar_update($.now(), $(".gravatar-profile").attr("src"));
};
$(function () {
// NB: This just binds to current elements, and won't bind to elements
// created after ready() is called.
@ -429,7 +475,7 @@ $(function () {
search.initialize();
$("body").bind('click', function() {
hide_userinfo_popover();
ui.hide_userinfo_popover();
});
$("#main_div").on("click", ".messagebox", function (e) {
@ -482,7 +528,7 @@ $(function () {
var row = $(this).closest(".message_row");
e.stopPropagation();
var last_popover_elem = current_userinfo_popover_elem;
hide_userinfo_popover();
ui.hide_userinfo_popover();
if (last_popover_elem === undefined
|| last_popover_elem.get()[0] !== this) {
// Only show the popover if either no popover is
@ -508,40 +554,5 @@ $(function () {
});
});
function update_gravatars() {
$.each($(".gravatar-profile"), function(index, profile) {
$(this).attr('src', $(this).attr('src') + '?stamp=' + gravatar_stamp);
});
gravatar_stamp += 1;
}
function poll_for_gravatar_update(start_time, url) {
var updated = false;
$.ajax({
type: "HEAD",
url: url,
async: false,
cache: false,
success: function (resp, statusText, xhr) {
if (new Date(xhr.getResponseHeader('Last-Modified')) > start_time) {
update_gravatars();
updated = true;
}
}
});
// Give users 5 minutes to update their picture on gravatar.com,
// during which we try to auto-update their image on our site. If
// they take longer than that, we'll update when they press the
// save button.
if (!updated && (($.now() - start_time) < 1000 * 60 * 5)) {
setTimeout(function() {
poll_for_gravatar_update(start_time, url);
}, 1500);
}
}
function wait_for_gravatar() {
poll_for_gravatar_update($.now(), $(".gravatar-profile").attr("src"));
}
return exports;
}());

View File

@ -326,7 +326,7 @@ function add_to_table(messages, table_name, filter_function, where, allow_collap
message.dom_id = table_name + message.id;
if (message.sender_email === email) {
message.stamp = gravatar_stamp;
message.stamp = ui.get_gravatar_stamp();
}
messages_to_render.push(message);