mirror of https://github.com/zulip/zulip.git
Add emoji map to the compose box.
- Expand a box full of emojis into the compose window for users to graphically select emojis. - Append an emoji to the end of the message when a user clicks the emoji in the emoji box. - Trap the escape key to always close the emoji box before closing anything else if the box is open. - Fixes: #147.
This commit is contained in:
parent
da86429378
commit
4bf908c2d6
|
@ -1,6 +1,12 @@
|
|||
set_global('page_params', {realm_emoji: {
|
||||
burrito: {display_url: '/static/third/gemoji/images/emoji/burrito.png',
|
||||
source_url: '/static/third/gemoji/images/emoji/burrito.png'}
|
||||
}});
|
||||
|
||||
add_dependencies({
|
||||
Handlebars: 'handlebars',
|
||||
templates: 'js/templates',
|
||||
emoji: 'js/emoji',
|
||||
i18n: 'i18next'
|
||||
});
|
||||
|
||||
|
@ -301,6 +307,20 @@ fs.readdirSync(path.join(__dirname, "../../static/templates/", "settings")).forE
|
|||
assert.equal(li.text(), 'The email will be forwarded to this stream');
|
||||
}());
|
||||
|
||||
(function emoji_popover_content() {
|
||||
var args = {
|
||||
emoji_list: global.emoji.emojis_name_to_css_class
|
||||
};
|
||||
|
||||
var html = '<div style="height: 250px">';
|
||||
html += render('emoji_popover_content', args);
|
||||
html += "</div>";
|
||||
// test to make sure the first emoji is present in the popover
|
||||
var emoji_key = $(html).find(".emoji-100").attr('title');
|
||||
assert.equal(emoji_key, ':100:');
|
||||
global.write_handlebars_output("emoji_popover_content", html);
|
||||
}());
|
||||
|
||||
(function group_pms() {
|
||||
var args = {
|
||||
"group_pms": [
|
||||
|
|
|
@ -286,6 +286,13 @@ $(function () {
|
|||
});
|
||||
|
||||
function handle_compose_click(e) {
|
||||
// Emoji clicks should be handled by their own click handler in popover.js
|
||||
if ($(e.target).is("#emoji_map") ||
|
||||
$(e.target).is(".emoji_popover") ||
|
||||
$(e.target).is(".emoji_popover.inner") ||
|
||||
$(e.target).is("img.emoji")) {
|
||||
return;
|
||||
}
|
||||
// Don't let clicks in the compose area count as
|
||||
// "unfocusing" our compose -- in other words, e.g.
|
||||
// clicking "Press enter to send" should not
|
||||
|
@ -418,7 +425,8 @@ $(function () {
|
|||
// of modals or selecting text (for copy+paste) trigger cancelling.
|
||||
if (compose.composing() && !$(e.target).is("a") &&
|
||||
($(e.target).closest(".modal").length === 0) &&
|
||||
window.getSelection().toString() === "") {
|
||||
window.getSelection().toString() === "" &&
|
||||
($(e.target).closest('#emoji_map').length === 0)) {
|
||||
compose.cancel();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -45,6 +45,13 @@ exports.update_emojis = function update_emojis(realm_emojis) {
|
|||
});
|
||||
};
|
||||
|
||||
exports.initialize = function initialize () {
|
||||
// Load the sprite image in the background so that the browser
|
||||
// can cache it for later use.
|
||||
var sprite = new Image();
|
||||
sprite.src = '/static/third/gemoji/sprite.png';
|
||||
};
|
||||
|
||||
exports.update_emojis(page_params.realm_emoji);
|
||||
|
||||
return exports;
|
||||
|
|
|
@ -195,6 +195,11 @@ function process_hotkey(e) {
|
|||
// Process hotkeys specially when in an input, select, textarea, or send button
|
||||
if ($('input:focus,select:focus,textarea:focus,#compose-send-button:focus').length > 0) {
|
||||
if (event_name === 'escape') {
|
||||
// emoji window should trap escape before it is able to close the compose box
|
||||
if ($('.emoji_popover').css('display') === 'inline-block') {
|
||||
popovers.hide_emoji_map_popover();
|
||||
return;
|
||||
}
|
||||
// If one of our typeaheads is open, do nothing so that the Esc
|
||||
// will go to close it
|
||||
if ($("#subject").data().typeahead.shown ||
|
||||
|
@ -270,7 +275,9 @@ function process_hotkey(e) {
|
|||
narrow.by('is', 'private', opts);
|
||||
});
|
||||
case 'escape': // Esc: close actions popup, cancel compose, clear a find, or un-narrow
|
||||
if (popovers.any_active()) {
|
||||
if ($('.emoji_popover').css('display') === 'inline-block') {
|
||||
popovers.hide_emoji_map_popover();
|
||||
} else if (popovers.any_active()) {
|
||||
popovers.hide_all();
|
||||
} else if (compose.composing()) {
|
||||
compose.cancel();
|
||||
|
|
|
@ -4,6 +4,7 @@ var exports = {};
|
|||
|
||||
var current_actions_popover_elem;
|
||||
var current_message_info_popover_elem;
|
||||
var emoji_map_is_open = false;
|
||||
|
||||
var userlist_placement = "right";
|
||||
|
||||
|
@ -209,6 +210,14 @@ function topic_sidebar_popped() {
|
|||
return current_topic_sidebar_elem !== undefined;
|
||||
}
|
||||
|
||||
exports.hide_emoji_map_popover = function () {
|
||||
if (emoji_map_is_open) {
|
||||
$('.emoji_popover').css('display', 'none');
|
||||
$('.drag').css('display', 'none');
|
||||
emoji_map_is_open = false;
|
||||
}
|
||||
};
|
||||
|
||||
exports.hide_stream_sidebar_popover = function () {
|
||||
if (stream_sidebar_popped()) {
|
||||
$(current_stream_sidebar_elem).popover("destroy");
|
||||
|
@ -237,6 +246,21 @@ exports.hide_user_sidebar_popover = function () {
|
|||
}
|
||||
};
|
||||
|
||||
function render_emoji_popover() {
|
||||
var content = templates.render('emoji_popover_content', {
|
||||
emoji_list: emoji.emojis_name_to_css_class
|
||||
});
|
||||
|
||||
$('.emoji_popover').append(content);
|
||||
|
||||
$('.drag').show();
|
||||
$('.emoji_popover').css('display', 'inline-block');
|
||||
|
||||
$("#new_message_content").focus();
|
||||
|
||||
emoji_map_is_open = true;
|
||||
}
|
||||
|
||||
exports.register_click_handlers = function () {
|
||||
$("#main_div").on("click", ".actions_hover", function (e) {
|
||||
var row = $(this).closest(".message_row");
|
||||
|
@ -250,6 +274,79 @@ exports.register_click_handlers = function () {
|
|||
show_message_info_popover(this, rows.id(row));
|
||||
});
|
||||
|
||||
var isDragging=false;
|
||||
var top_border = $('#floating_recipient_bar').position().top + $('#floating_recipient_bar').height();
|
||||
var total_height;
|
||||
var emoji_popover_height;
|
||||
var emoji_popover_elem;
|
||||
var previous_mouse_position;
|
||||
var compose_box_padding;
|
||||
var emoji_height = 25;
|
||||
$("body").on("mouseover", ".emoji_popover", function (e) {
|
||||
total_height = $('body > .app').outerHeight() - top_border - 70;
|
||||
if (total_height <= 300) {
|
||||
// don't allow dragging if the viewport is small enough that it
|
||||
// would obscure everything to drag the emojis
|
||||
$('.drag').hide();
|
||||
} else {
|
||||
$('.drag').show();
|
||||
}
|
||||
});
|
||||
|
||||
$("body").on("mousedown", ".drag", function (e) {
|
||||
// leave a little extra padding for the message box so that it doesn't get too big
|
||||
total_height = $('body > .app').outerHeight() - top_border - 70;
|
||||
isDragging = true;
|
||||
previous_mouse_position = e.pageY;
|
||||
emoji_popover_elem = $(".emoji_popover");
|
||||
emoji_popover_height = emoji_popover_elem.height();
|
||||
compose_box_padding = $('#compose').height() - emoji_popover_height;
|
||||
});
|
||||
|
||||
$("body").on("mousemove", function (e) {
|
||||
e.preventDefault();
|
||||
if (isDragging) {
|
||||
var new_height = emoji_popover_height + (previous_mouse_position - e.pageY);
|
||||
if (new_height + compose_box_padding > total_height) {
|
||||
emoji_popover_elem.height(total_height - compose_box_padding);
|
||||
} else if (new_height < emoji_height) {
|
||||
emoji_popover_elem.height(emoji_height);
|
||||
} else {
|
||||
emoji_popover_elem.height(new_height);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("body").on("mouseup", function (e) {
|
||||
isDragging = false;
|
||||
emoji_popover_height = null;
|
||||
});
|
||||
|
||||
|
||||
$("body").on("click", ".emoji_popover", function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$(".emoji_popover").on("click", ".emoji", function (e) {
|
||||
var emoji_choice = $(e.target).attr("title");
|
||||
var textarea = $("#new_message_content");
|
||||
textarea.val(textarea.val() + " " + emoji_choice);
|
||||
textarea.focus();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$("#compose").on("click", "#emoji_map", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (emoji_map_is_open) {
|
||||
// If the popover is already shown, clicking again should toggle it.
|
||||
popovers.hide_emoji_map_popover();
|
||||
return;
|
||||
}
|
||||
popovers.hide_all();
|
||||
render_emoji_popover();
|
||||
});
|
||||
|
||||
$('body').on('click', '.user_popover .narrow_to_private_messages', function (e) {
|
||||
var email = $(e.target).parents('ul').attr('data-email');
|
||||
popovers.hide_user_sidebar_popover();
|
||||
|
@ -597,7 +694,7 @@ exports.register_click_handlers = function () {
|
|||
|
||||
exports.any_active = function () {
|
||||
// True if any popover (that this module manages) is currently shown.
|
||||
return popovers.actions_popped() || user_sidebar_popped() || stream_sidebar_popped() || topic_sidebar_popped() || message_info_popped();
|
||||
return popovers.actions_popped() || user_sidebar_popped() || stream_sidebar_popped() || topic_sidebar_popped() || message_info_popped() || emoji_map_is_open;
|
||||
};
|
||||
|
||||
exports.hide_all = function () {
|
||||
|
@ -608,6 +705,7 @@ exports.hide_all = function () {
|
|||
popovers.hide_user_sidebar_popover();
|
||||
popovers.hide_userlist_sidebar();
|
||||
popovers.hide_streamlist_sidebar();
|
||||
popovers.hide_emoji_map_popover();
|
||||
};
|
||||
|
||||
exports.set_userlist_placement = function (placement) {
|
||||
|
|
|
@ -396,6 +396,11 @@ $(function () {
|
|||
}
|
||||
});
|
||||
|
||||
// Override the #compose mousewheel prevention below just for the emoji box
|
||||
$('.emoji_popover').mousewheel(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Ignore wheel events in the compose area which weren't already handled above.
|
||||
$('#compose').mousewheel(function (e) {
|
||||
e.stopPropagation();
|
||||
|
@ -527,6 +532,7 @@ $(function () {
|
|||
hashchange.initialize();
|
||||
invite.initialize();
|
||||
activity.initialize();
|
||||
emoji.initialize();
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -3315,6 +3315,44 @@ li.expanded_private_message {
|
|||
color: #000;
|
||||
}
|
||||
|
||||
.drag {
|
||||
display: none;
|
||||
height: 18px;
|
||||
width: 100%;
|
||||
top: 23px;
|
||||
position: relative;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.emoji_popover {
|
||||
display: none;
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
bottom: 0px;
|
||||
z-index: 1010;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
padding: 1px;
|
||||
text-align: center;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.emoji_popover .emoji {
|
||||
margin: 2px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.emoji_popover .emoji:active {
|
||||
border-radius: 5px;
|
||||
border: 2px white solid;
|
||||
}
|
||||
|
||||
#enter_sends {
|
||||
margin-top: 0px;
|
||||
margin-right: 5px;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{{! Contents of the "emoji map" popup }}
|
||||
{{#each emoji_list}}
|
||||
<div class="emoji emoji-{{this}}" title= ":{{@key}}:" />
|
||||
{{/each}}
|
||||
|
|
@ -74,8 +74,12 @@
|
|||
<div id="markdown_preview_spinner"></div>
|
||||
<div id="preview_content"></div>
|
||||
</div>
|
||||
<div class="drag"></div>
|
||||
<div class="emoji_popover"></div>
|
||||
<div id="below-compose-content">
|
||||
<input type="file" id="file_input" class="notvisible pull-left" multiple />
|
||||
<a class="message-control-button icon-vector-smile"
|
||||
id="emoji_map" href="#"></a>
|
||||
<a class="message-control-button icon-vector-dropbox notdisplayed"
|
||||
id="attach_dropbox_files" href="#" title="{{ _('Attach files from Dropbox') }}"></a>
|
||||
<a class="message-control-button icon-vector-paper-clip notdisplayed"
|
||||
|
|
|
@ -14,6 +14,7 @@ var page_params = {{ page_params }};
|
|||
{% block customhead %}
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="/static/images/logo/apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed">
|
||||
<link rel="stylesheet" type="text/css" href="/static/third/gemoji/sprite.css" />
|
||||
<style type="text/css">
|
||||
|
||||
#css-loading {
|
||||
|
|
Loading…
Reference in New Issue