Add support for Emojis
This commit is contained in:
parent
fb69106352
commit
ca53a8d8ef
|
@ -2,6 +2,7 @@
|
|||
|
||||
## 3.1.0 (Unreleased)
|
||||
|
||||
- Add support for Emojis (uses <a href="https://www.emojione.com/">Emojione</a>).
|
||||
- New non-core plugin `converse-singleton` which ensures that no more than
|
||||
one chat is visible at any given time. Used in the mobile build:
|
||||
`converse-mobile.js` and makes the unread messages counter possible there.
|
||||
|
|
|
@ -1260,6 +1260,9 @@
|
|||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
transform: rotate(359deg); } }
|
||||
#converse-embedded-chat .emojione,
|
||||
#conversejs .emojione {
|
||||
height: 24px; }
|
||||
#converse-embedded-chat .spinner,
|
||||
#conversejs .spinner {
|
||||
-webkit-animation: spin 2s infinite, linear;
|
||||
|
@ -1739,7 +1742,6 @@
|
|||
background: #fff;
|
||||
bottom: 100%;
|
||||
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
|
@ -1762,6 +1764,16 @@
|
|||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul {
|
||||
left: 0; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker {
|
||||
z-index: 100; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker .picked,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker .picked {
|
||||
background-color: #DCF9F6; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-picker,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-picker {
|
||||
height: 250px;
|
||||
overflow: scroll; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul li,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul li {
|
||||
font-size: 14px;
|
||||
|
@ -1956,7 +1968,7 @@
|
|||
#conversejs #controlbox #chatrooms .rooms-list-container dl.rooms-list dd.available-chatroom a:hover {
|
||||
color: #206485; }
|
||||
#conversejs #controlbox #chatrooms .rooms-list-container dl.rooms-list dd.available-chatroom.unread-msgs .open-room {
|
||||
max-width: 50%;
|
||||
max-width: 55%;
|
||||
width: auto;
|
||||
font-weight: bold; }
|
||||
#conversejs #controlbox #chatrooms .rooms-list-container dl.rooms-list dd.available-chatroom a.room-info:before {
|
||||
|
@ -2286,16 +2298,22 @@
|
|||
#conversejs #converse-roster .roster-contacts dd .open-chat.unread-msgs .contact-name {
|
||||
width: 70%; }
|
||||
#conversejs #converse-roster .roster-contacts dd .open-chat .msgs-indicator {
|
||||
background-color: #E7A151;
|
||||
opacity: 1;
|
||||
border-radius: 10%;
|
||||
padding: 0 0.2em;
|
||||
font-size: 12px; }
|
||||
#conversejs #converse-roster .roster-contacts dd .open-chat .contact-name {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-width: 80%;
|
||||
float: none;
|
||||
height: 60px; }
|
||||
#conversejs #converse-roster .roster-contacts dd .open-chat .contact-name.unread-msgs {
|
||||
max-width: 60%; }
|
||||
#conversejs #converse-roster .roster-contacts dd .open-chat .avatar {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
|
|
|
@ -1260,6 +1260,9 @@
|
|||
-ms-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
transform: rotate(359deg); } }
|
||||
#converse-embedded-chat .emojione,
|
||||
#conversejs .emojione {
|
||||
height: 24px; }
|
||||
#converse-embedded-chat .spinner,
|
||||
#conversejs .spinner {
|
||||
-webkit-animation: spin 2s infinite, linear;
|
||||
|
@ -1785,7 +1788,6 @@ body {
|
|||
background: #fff;
|
||||
bottom: 100%;
|
||||
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
|
@ -1808,6 +1810,16 @@ body {
|
|||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul {
|
||||
left: 0; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker {
|
||||
z-index: 100; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker .picked,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-category-picker .picked {
|
||||
background-color: #DCF9F6; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-picker,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul.emoji-picker {
|
||||
height: 250px;
|
||||
overflow: scroll; }
|
||||
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul li,
|
||||
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar .toggle-smiley ul li {
|
||||
font-size: 16px;
|
||||
|
|
|
@ -993,6 +993,14 @@ Notification will be shown in the following cases:
|
|||
|
||||
Requires the `src/converse-notification.js` plugin.
|
||||
|
||||
show_emojione
|
||||
-------------
|
||||
* Default: ``false``
|
||||
|
||||
Determines whether `Emojione <https://www.emojione.com/>`_ should be used to
|
||||
render emojis. The default is not to do this, but to simply let the operating
|
||||
system or browser render emoji (if it has support for them).
|
||||
|
||||
show_only_online_users
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"bootstrap": "^3.3.7",
|
||||
"bourbon": "^4.3.2",
|
||||
"clean-css-cli": "^4.0.10",
|
||||
"emojione": "^3.0.3",
|
||||
"es6-promise": "^4.1.0",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-plugin-lodash": "^2.3.3",
|
||||
|
|
|
@ -309,7 +309,6 @@
|
|||
background: #fff;
|
||||
bottom: 100%;
|
||||
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.4);
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
|
@ -330,6 +329,16 @@
|
|||
color: $link-color;
|
||||
padding-left: 5px;
|
||||
ul {
|
||||
&.emoji-category-picker {
|
||||
z-index: 100;
|
||||
.picked {
|
||||
background-color: $highlight-color;
|
||||
}
|
||||
}
|
||||
&.emoji-picker {
|
||||
height: 250px;
|
||||
overflow: scroll;
|
||||
}
|
||||
left: 0;
|
||||
li {
|
||||
font-size: $font-size;
|
||||
|
|
|
@ -91,6 +91,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.emojione {
|
||||
height: $emoji_height;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
@include animation(spin 2s infinite, linear);
|
||||
display: block;
|
||||
|
|
|
@ -47,8 +47,11 @@ $save-button-color: $green !default;
|
|||
$chat-textarea-height: 70px !default;
|
||||
$send-button-height: 27px !default;
|
||||
$send-button-margin: 3px !default;
|
||||
|
||||
$message-them-color: $green !default;
|
||||
|
||||
$emoji_height : 24px !default;
|
||||
|
||||
$roster-height: 194px !default;
|
||||
$roster-item-height: 60px !default;
|
||||
|
||||
|
|
|
@ -47,8 +47,11 @@ $save-button-color: $green !default;
|
|||
$chat-textarea-height: 70px !default;
|
||||
$send-button-height: 27px !default;
|
||||
$send-button-margin: 3px !default;
|
||||
|
||||
$message-them-color: $green !default;
|
||||
|
||||
$emoji_height : 24px !default;
|
||||
|
||||
$roster-height: 194px !default;
|
||||
$roster-item-height: 30px !default;
|
||||
|
||||
|
|
|
@ -351,42 +351,22 @@
|
|||
expect($toolbar.children('li.toggle-smiley').length).toBe(1);
|
||||
// Register spies
|
||||
spyOn(view, 'toggleEmoticonMenu').and.callThrough();
|
||||
spyOn(view, 'insertEmoticon').and.callThrough();
|
||||
spyOn(view, 'insertEmoticon');
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
$toolbar.children('li.toggle-smiley').click();
|
||||
|
||||
expect(view.toggleEmoticonMenu).toHaveBeenCalled();
|
||||
var $menu = view.$el.find('.toggle-smiley ul');
|
||||
var $items = $menu.children('li');
|
||||
expect($menu.is(':visible')).toBeTruthy();
|
||||
expect($items.length).toBe(13);
|
||||
expect($($items[0]).children('a').data('emoticon')).toBe(':)');
|
||||
expect($($items[1]).children('a').data('emoticon')).toBe(';)');
|
||||
expect($($items[2]).children('a').data('emoticon')).toBe(':D');
|
||||
expect($($items[3]).children('a').data('emoticon')).toBe(':P');
|
||||
expect($($items[4]).children('a').data('emoticon')).toBe('8)');
|
||||
expect($($items[5]).children('a').data('emoticon')).toBe('>:)');
|
||||
expect($($items[6]).children('a').data('emoticon')).toBe(':S');
|
||||
expect($($items[7]).children('a').data('emoticon')).toBe(':\\');
|
||||
expect($($items[8]).children('a').data('emoticon')).toBe('>:(');
|
||||
expect($($items[9]).children('a').data('emoticon')).toBe(':(');
|
||||
expect($($items[10]).children('a').data('emoticon')).toBe(':O');
|
||||
expect($($items[11]).children('a').data('emoticon')).toBe('(^.^)b');
|
||||
expect($($items[12]).children('a').data('emoticon')).toBe('<3');
|
||||
var $picker = view.$el.find('.toggle-smiley .emoji-picker-container');
|
||||
// expect($picker.is(':visible')).toBeTruthy();
|
||||
// expect(view.toggleEmoticonMenu).toHaveBeenCalled();
|
||||
var $items = $picker.find('.emoji-picker li');
|
||||
$items.first().click();
|
||||
|
||||
expect(view.insertEmoticon).toHaveBeenCalled();
|
||||
expect($textarea.val()).toBe(':) ');
|
||||
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy();
|
||||
$toolbar.children('li.toggle-smiley').click();
|
||||
|
||||
expect(view.toggleEmoticonMenu).toHaveBeenCalled();
|
||||
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeTruthy();
|
||||
view.$el.find('.toggle-smiley ul').children('li').last().click();
|
||||
|
||||
expect(view.insertEmoticon).toHaveBeenCalled();
|
||||
expect(view.$el.find('.toggle-smiley ul').is(':visible')).toBeFalsy();
|
||||
expect($textarea.val()).toBe(':) <3 ');
|
||||
done();
|
||||
});
|
||||
}));
|
||||
|
@ -411,11 +391,7 @@
|
|||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
|
||||
$toolbar.children('li.toggle-otr').click();
|
||||
|
||||
expect(view.toggleOTRMenu).toHaveBeenCalled();
|
||||
var $menu = view.$el.find('.toggle-otr ul');
|
||||
expect($menu.is(':visible')).toBeTruthy();
|
||||
expect($menu.children('li').length).toBe(2);
|
||||
done();
|
||||
});
|
||||
}));
|
||||
|
@ -1139,34 +1115,6 @@
|
|||
expect(msg.html()).toEqual('<p>This message contains <em>some</em> <b>markup</b></p>');
|
||||
}));
|
||||
|
||||
it("should display emoticons correctly", mock.initConverse(function (_converse) {
|
||||
test_utils.createContacts(_converse, 'current');
|
||||
test_utils.openControlBox();
|
||||
test_utils.openContactsPanel(_converse);
|
||||
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
test_utils.openChatBoxFor(_converse, contact_jid);
|
||||
var view = _converse.chatboxviews.get(contact_jid);
|
||||
var messages = [':)', ';)', ':D', ':P', '8)', '>:)', ':S', ':\\', '>:(', ':(', ':O', '(^.^)b', '<3'];
|
||||
var emoticons = [
|
||||
'<span class="emoticon icon-smiley"></span>', '<span class="emoticon icon-wink"></span>',
|
||||
'<span class="emoticon icon-grin"></span>', '<span class="emoticon icon-tongue"></span>',
|
||||
'<span class="emoticon icon-cool"></span>', '<span class="emoticon icon-evil"></span>',
|
||||
'<span class="emoticon icon-confused"></span>', '<span class="emoticon icon-wondering"></span>',
|
||||
'<span class="emoticon icon-angry"></span>', '<span class="emoticon icon-sad"></span>',
|
||||
'<span class="emoticon icon-shocked"></span>', '<span class="emoticon icon-thumbs-up"></span>',
|
||||
'<span class="emoticon icon-heart"></span>'
|
||||
];
|
||||
spyOn(view, 'sendMessage').and.callThrough();
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var message = messages[i];
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-msg-content');
|
||||
expect(msg.html()).toEqual(emoticons[i]);
|
||||
}
|
||||
}));
|
||||
|
||||
it("can contain hyperlinks, which will be clickable", mock.initConverse(function (_converse) {
|
||||
test_utils.createContacts(_converse, 'current');
|
||||
test_utils.openControlBox();
|
||||
|
|
|
@ -21,6 +21,7 @@ require.config({
|
|||
"backbone.noconflict": "src/backbone.noconflict",
|
||||
"backbone.browserStorage": "node_modules/backbone.browserStorage/backbone.browserStorage",
|
||||
"backbone.overview": "node_modules/backbone.overview/backbone.overview",
|
||||
"emojione": "node_modules/emojione/lib/js/emojione",
|
||||
"eventemitter": "node_modules/otr/build/dep/eventemitter",
|
||||
"es6-promise": "node_modules/es6-promise/dist/es6-promise",
|
||||
"jquery": "node_modules/jquery/dist/jquery",
|
||||
|
@ -136,6 +137,7 @@ require.config({
|
|||
|
||||
// define module dependencies for modules not using define
|
||||
shim: {
|
||||
'awesomplete': { exports: 'Awesomplete' }
|
||||
'awesomplete': { exports: 'Awesomplete'},
|
||||
'emojione': { exports: 'emojione'},
|
||||
}
|
||||
});
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
(function (root, factory) {
|
||||
define([
|
||||
"converse-core",
|
||||
"emojione",
|
||||
"tpl!chatbox",
|
||||
"tpl!new_day",
|
||||
"tpl!action",
|
||||
"tpl!emojis",
|
||||
"tpl!message",
|
||||
"tpl!help_message",
|
||||
"tpl!toolbar",
|
||||
|
@ -20,9 +22,11 @@
|
|||
], factory);
|
||||
}(this, function (
|
||||
converse,
|
||||
emojione,
|
||||
tpl_chatbox,
|
||||
tpl_new_day,
|
||||
tpl_action,
|
||||
tpl_emojis,
|
||||
tpl_message,
|
||||
tpl_help_message,
|
||||
tpl_toolbar,
|
||||
|
@ -43,7 +47,6 @@
|
|||
FORWARD_SLASH: 47
|
||||
};
|
||||
|
||||
|
||||
converse.plugins.add('converse-chatview', {
|
||||
|
||||
overrides: {
|
||||
|
@ -52,6 +55,18 @@
|
|||
// relevant objects or classes.
|
||||
//
|
||||
// New functions which don't exist yet can also be added.
|
||||
//
|
||||
registerGlobalEventHandlers: function () {
|
||||
this.__super__.registerGlobalEventHandlers();
|
||||
document.addEventListener('click', function () {
|
||||
if ($('.toggle-smiley ul').is(':visible')) {
|
||||
_.each(
|
||||
document.querySelectorAll('.toggle-smiley .emoji-picker-container'),
|
||||
utils.hideElement
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ChatBoxViews: {
|
||||
onChatBoxAdded: function (item) {
|
||||
|
@ -68,7 +83,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
|
||||
initialize: function () {
|
||||
/* The initialize function gets called as soon as the plugin is
|
||||
* loaded by converse.js's plugin machinery.
|
||||
|
@ -78,7 +92,9 @@
|
|||
|
||||
this.updateSettings({
|
||||
chatview_avatar_height: 32,
|
||||
chatview_avatar_width: 32,
|
||||
chatview_avatartrue: 32,
|
||||
show_emojione: false, // By default, use native emojis.
|
||||
emojione_path: 'https://cdn.jsdelivr.net/emojione/assets/' + emojione.emojiVersion + '/png/' + emojione.emojiSize + '/',
|
||||
show_toolbar: true,
|
||||
time_format: 'HH:mm',
|
||||
visible_toolbar_buttons: {
|
||||
|
@ -88,15 +104,65 @@
|
|||
},
|
||||
});
|
||||
|
||||
if (_converse.show_emojione) {
|
||||
// If using Emojione, we also convert ascii smileys into emoji.
|
||||
emojione.ascii = true;
|
||||
emojione.imagePathPNG = _converse.emojione_path
|
||||
}
|
||||
|
||||
var onWindowStateChanged = function (data) {
|
||||
var state = data.state;
|
||||
_converse.chatboxviews.each(function (chatboxview) {
|
||||
chatboxview.onWindowStateChanged(state);
|
||||
})
|
||||
};
|
||||
|
||||
_converse.api.listen.on('windowStateChanged', onWindowStateChanged);
|
||||
|
||||
|
||||
_converse.EmojiPicker = Backbone.Model.extend({
|
||||
defaults: {
|
||||
'current_category': 'people'
|
||||
}
|
||||
});
|
||||
|
||||
_converse.EmojiPickerView = Backbone.View.extend({
|
||||
className: 'emoji-picker-container hidden',
|
||||
events: {
|
||||
'click .emoji-category-picker li a': 'chooseCategory',
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.model.on('change', this.render, this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var emojis_by_category = utils.marshallEmojis(emojione);
|
||||
var converter;
|
||||
if (_converse.show_emojione) {
|
||||
converter = emojione.toImage
|
||||
} else {
|
||||
converter = emojione.shortnameToUnicode
|
||||
}
|
||||
var emojis_html = tpl_emojis(
|
||||
_.extend(
|
||||
this.model.toJSON(), {
|
||||
'emojis_by_category': emojis_by_category,
|
||||
'emojione': emojione,
|
||||
'converter': converter
|
||||
}
|
||||
));
|
||||
this.el.innerHTML = emojis_html;
|
||||
return this;
|
||||
},
|
||||
|
||||
chooseCategory: function (ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
var category = ev.target.parentElement.getAttribute("data-category").trim();
|
||||
this.model.set({'current_category': category});
|
||||
}
|
||||
});
|
||||
|
||||
_converse.ChatBoxView = Backbone.View.extend({
|
||||
length: 200,
|
||||
tagName: 'div',
|
||||
|
@ -108,13 +174,15 @@
|
|||
'keypress .chat-textarea': 'keyPressed',
|
||||
'click .send-button': 'onSendButtonClicked',
|
||||
'click .toggle-smiley': 'toggleEmoticonMenu',
|
||||
'click .toggle-smiley ul li': 'insertEmoticon',
|
||||
'click .toggle-smiley ul.emoji-picker li': 'insertEmoticon',
|
||||
'click .toggle-clear': 'clearMessages',
|
||||
'click .toggle-call': 'toggleCall',
|
||||
'click .new-msgs-indicator': 'viewUnreadMessages'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.emoji_picker_view = new _converse.EmojiPickerView({model: new _converse.EmojiPicker() });
|
||||
|
||||
this.model.messages.on('add', this.onMessageAdded, this);
|
||||
this.model.on('show', this.show, this);
|
||||
this.model.on('destroy', this.hide, this);
|
||||
|
@ -374,7 +442,10 @@
|
|||
$msg.find('.chat-msg-content').first()
|
||||
.text(text)
|
||||
.addHyperlinks()
|
||||
.addEmoticons(_converse.visible_toolbar_buttons.emoticons);
|
||||
.addEmoticons(
|
||||
_converse,
|
||||
emojione,
|
||||
_converse.visible_toolbar_buttons.emoticons);
|
||||
return $msg;
|
||||
},
|
||||
|
||||
|
@ -642,15 +713,24 @@
|
|||
|
||||
insertEmoticon: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this.$el.find('.toggle-smiley ul').slideToggle(200);
|
||||
var $target = $(ev.target);
|
||||
$target = $target.is('a') ? $target : $target.children('a');
|
||||
this.insertIntoTextArea($target.data('emoticon'));
|
||||
this.toggleEmoticonMenu();
|
||||
var target;
|
||||
if (ev.target.nodeName === 'IMG') {
|
||||
target = ev.target.parentElement;
|
||||
} else {
|
||||
target = ev.target;
|
||||
}
|
||||
this.insertIntoTextArea(
|
||||
emojione.shortnameToUnicode(
|
||||
target.getAttribute('data-emoticon')
|
||||
));
|
||||
},
|
||||
|
||||
toggleEmoticonMenu: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this.$el.find('.toggle-smiley ul').slideToggle(200);
|
||||
if (!_.isUndefined(ev)) {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
utils.toggleElement(this.emoji_picker_view.el);
|
||||
},
|
||||
|
||||
toggleCall: function (ev) {
|
||||
|
@ -726,11 +806,15 @@
|
|||
renderToolbar: function (toolbar, options) {
|
||||
if (!_converse.show_toolbar) { return; }
|
||||
toolbar = toolbar || tpl_toolbar;
|
||||
options = _.extend(
|
||||
options = _.assign(
|
||||
this.model.toJSON(),
|
||||
this.getToolbarOptions(options || {})
|
||||
);
|
||||
this.$el.find('.chat-toolbar').html(toolbar(options));
|
||||
this.el.querySelector('.chat-toolbar').innerHTML = toolbar(options);
|
||||
|
||||
var toggle = this.el.querySelector('.toggle-smiley');
|
||||
toggle.innerHTML = '';
|
||||
toggle.appendChild(this.emoji_picker_view.render().el);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
|
@ -449,6 +449,8 @@
|
|||
this.model.on('change:description', this.renderHeading, this);
|
||||
this.model.on('change:name', this.renderHeading, this);
|
||||
|
||||
this.emoji_picker_view = new _converse.EmojiPickerView({model: new _converse.EmojiPicker() });
|
||||
|
||||
this.createOccupantsView();
|
||||
this.render().insertIntoDOM();
|
||||
this.registerHandlers();
|
||||
|
|
|
@ -58,12 +58,9 @@
|
|||
|
||||
registerGlobalEventHandlers: function () {
|
||||
this.__super__.registerGlobalEventHandlers();
|
||||
$(document).click(function () {
|
||||
document.addEventListener('click', function () {
|
||||
if ($('.toggle-otr ul').is(':visible')) {
|
||||
$('.toggle-otr ul', this).slideUp();
|
||||
}
|
||||
if ($('.toggle-smiley ul').is(':visible')) {
|
||||
$('.toggle-smiley ul', this).slideUp();
|
||||
_.each($('.toggle-otr ul', this), utils.hideElement);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -400,7 +397,7 @@
|
|||
|
||||
toggleOTRMenu: function (ev) {
|
||||
ev.stopPropagation();
|
||||
this.$el.find('.toggle-otr ul').slideToggle(200);
|
||||
utils.toggleElement(this.el.querySelector('.toggle-otr ul'));
|
||||
},
|
||||
|
||||
getOTRTooltip: function () {
|
||||
|
@ -444,9 +441,9 @@
|
|||
});
|
||||
this.__super__.renderToolbar.apply(this, arguments);
|
||||
this.$el.find('.chat-toolbar').append(
|
||||
tpl_toolbar_otr(
|
||||
_.extend(this.model.toJSON(), options || {})
|
||||
));
|
||||
tpl_toolbar_otr(
|
||||
_.extend(this.model.toJSON(), options || {})
|
||||
));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
{[ if (show_emoticons) { ]}
|
||||
<li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
<ul class="emoji-picker"></ul>
|
||||
</li>
|
||||
{[ } ]}
|
||||
{[ if (show_call_button) { ]}
|
||||
|
|
|
@ -1,21 +1,5 @@
|
|||
{[ if (show_emoticons) { ]}
|
||||
<li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toggle-smiley icon-happy" title="{{{label_insert_smiley}}}"></li>
|
||||
{[ } ]}
|
||||
{[ if (show_call_button) { ]}
|
||||
<li class="toggle-call"><a class="icon-phone" title="{{{label_start_call}}}"></a></li>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{[ if (otr_status == FINISHED) { ]}
|
||||
<span class="icon-unlocked"></span>
|
||||
{[ } ]}
|
||||
<ul>
|
||||
<ul class="hidden">
|
||||
{[ if (otr_status == UNENCRYPTED) { ]}
|
||||
<li><a class="start-otr" href="#">{{{label_start_encrypted_conversation}}}</a></li>
|
||||
{[ } ]}
|
||||
|
|
85
src/utils.js
85
src/utils.js
|
@ -115,7 +115,10 @@
|
|||
_.forEach(list, function (url) {
|
||||
isImage(unescapeHTML(url)).then(function (img) {
|
||||
img.className = 'chat-image';
|
||||
throttledHTML(obj.querySelector('a'), img.outerHTML);
|
||||
var a = obj.querySelector('a');
|
||||
if (!_.isNull(a)) {
|
||||
throttledHTML(a, img.outerHTML);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -123,36 +126,12 @@
|
|||
return this;
|
||||
};
|
||||
|
||||
$.fn.addEmoticons = function (allowed) {
|
||||
$.fn.addEmoticons = function (_converse, emojione, allowed) {
|
||||
if (allowed) {
|
||||
if (this.length > 0) {
|
||||
this.each(function (i, obj) {
|
||||
var text = $(obj).html();
|
||||
text = text.replace(/>:\)/g, '<span class="emoticon icon-evil"></span>');
|
||||
text = text.replace(/:\)/g, '<span class="emoticon icon-smiley"></span>');
|
||||
text = text.replace(/:\-\)/g, '<span class="emoticon icon-smiley"></span>');
|
||||
text = text.replace(/;\)/g, '<span class="emoticon icon-wink"></span>');
|
||||
text = text.replace(/;\-\)/g, '<span class="emoticon icon-wink"></span>');
|
||||
text = text.replace(/:D/g, '<span class="emoticon icon-grin"></span>');
|
||||
text = text.replace(/:\-D/g, '<span class="emoticon icon-grin"></span>');
|
||||
text = text.replace(/:P/g, '<span class="emoticon icon-tongue"></span>');
|
||||
text = text.replace(/:\-P/g, '<span class="emoticon icon-tongue"></span>');
|
||||
text = text.replace(/:p/g, '<span class="emoticon icon-tongue"></span>');
|
||||
text = text.replace(/:\-p/g, '<span class="emoticon icon-tongue"></span>');
|
||||
text = text.replace(/8\)/g, '<span class="emoticon icon-cool"></span>');
|
||||
text = text.replace(/:S/g, '<span class="emoticon icon-confused"></span>');
|
||||
text = text.replace(/:\\/g, '<span class="emoticon icon-wondering"></span>');
|
||||
text = text.replace(/:\/ /g, '<span class="emoticon icon-wondering"></span>');
|
||||
text = text.replace(/>:\(/g, '<span class="emoticon icon-angry"></span>');
|
||||
text = text.replace(/:\(/g, '<span class="emoticon icon-sad"></span>');
|
||||
text = text.replace(/:\-\(/g, '<span class="emoticon icon-sad"></span>');
|
||||
text = text.replace(/:O/g, '<span class="emoticon icon-shocked"></span>');
|
||||
text = text.replace(/:\-O/g, '<span class="emoticon icon-shocked"></span>');
|
||||
text = text.replace(/\=\-O/g, '<span class="emoticon icon-shocked"></span>');
|
||||
text = text.replace(/\(\^.\^\)b/g, '<span class="emoticon icon-thumbs-up"></span>');
|
||||
text = text.replace(/<3/g, '<span class="emoticon icon-heart"></span>');
|
||||
$(obj).html(text);
|
||||
});
|
||||
if (_converse.show_emojione) {
|
||||
this.html(emojione.toImage(this.text()));
|
||||
} else {
|
||||
this.html(emojione.shortnameToUnicode(this.text()));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
@ -203,6 +182,19 @@
|
|||
}
|
||||
},
|
||||
|
||||
hideElement: function (el) {
|
||||
el.classList.add('hidden');
|
||||
},
|
||||
|
||||
toggleElement: function (el) {
|
||||
if (_.includes(el.classList, 'hidden')) {
|
||||
// XXX: use fadeIn?
|
||||
el.classList.remove('hidden');
|
||||
} else {
|
||||
this.hideElement (el);
|
||||
}
|
||||
},
|
||||
|
||||
fadeIn: function (el, callback) {
|
||||
if ($.fx.off) {
|
||||
el.classList.remove('hidden');
|
||||
|
@ -522,5 +514,38 @@
|
|||
frag = tmp = null;
|
||||
}
|
||||
|
||||
utils.marshallEmojis = function (emojione) {
|
||||
/* Return a dict of emojis with the categories as keys and
|
||||
* lists of emojis in that category as values.
|
||||
*/
|
||||
if (_.isUndefined(this.emojis_by_category)) {
|
||||
var emojis = _.values(_.mapValues(emojione.emojioneList, function (value, key, o) {
|
||||
value._shortname = key;
|
||||
return value
|
||||
}));
|
||||
var tones = [':tone1:', ':tone2:', ':tone3:', ':tone4:', ':tone5:'];
|
||||
var categories = _.uniq(_.map(emojis, _.partial(_.get, _, 'category')));
|
||||
var emojis_by_category = {};
|
||||
_.forEach(categories, function (cat) {
|
||||
var list = _.sortBy(_.filter(emojis, ['category', cat]), ['uc_base']);
|
||||
list = _.filter(list, function (item) {
|
||||
return !_.includes(tones, item._shortname);
|
||||
});
|
||||
if (cat === 'people') {
|
||||
var idx = _.findIndex(list, ['uc_base', '1f600']);
|
||||
list = _.union(_.slice(list, idx), _.slice(list, 0, idx+1));
|
||||
} else if (cat === 'activity') {
|
||||
list = _.union(_.slice(list, 27-1), _.slice(list, 0, 27));
|
||||
} else if (cat === 'objects') {
|
||||
list = _.union(_.slice(list, 24-1), _.slice(list, 0, 24));
|
||||
} else if (cat === 'travel') {
|
||||
list = _.union(_.slice(list, 17-1), _.slice(list, 0, 17));
|
||||
}
|
||||
emojis_by_category[cat] = list;
|
||||
});
|
||||
this.emojis_by_category = emojis_by_category;
|
||||
}
|
||||
return this.emojis_by_category;
|
||||
}
|
||||
return utils;
|
||||
}));
|
||||
|
|
Loading…
Reference in New Issue
Block a user