From 102f39ed41f4bfac89b8c3d323334741f8947ba2 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Wed, 20 Dec 2017 17:08:08 +0000 Subject: [PATCH] Regenerate po, pot and json --- dist/converse-no-dependencies.js | 4918 +++++++++--------------- locale/af/LC_MESSAGES/converse.json | 94 +- locale/af/LC_MESSAGES/converse.po | 715 ++-- locale/ca/LC_MESSAGES/converse.json | 42 +- locale/ca/LC_MESSAGES/converse.po | 705 ++-- locale/converse.pot | 692 ++-- locale/de/LC_MESSAGES/converse.json | 322 +- locale/de/LC_MESSAGES/converse.po | 719 ++-- locale/es/LC_MESSAGES/converse.json | 46 +- locale/es/LC_MESSAGES/converse.po | 704 ++-- locale/fr/LC_MESSAGES/converse.json | 196 +- locale/fr/LC_MESSAGES/converse.po | 723 ++-- locale/he/LC_MESSAGES/converse.json | 38 +- locale/he/LC_MESSAGES/converse.po | 704 ++-- locale/hu/LC_MESSAGES/converse.json | 42 +- locale/hu/LC_MESSAGES/converse.po | 705 ++-- locale/id/LC_MESSAGES/converse.json | 50 +- locale/id/LC_MESSAGES/converse.po | 704 ++-- locale/it/LC_MESSAGES/converse.json | 224 +- locale/it/LC_MESSAGES/converse.po | 715 ++-- locale/ja/LC_MESSAGES/converse.json | 46 +- locale/ja/LC_MESSAGES/converse.po | 704 ++-- locale/nb/LC_MESSAGES/converse.json | 320 +- locale/nb/LC_MESSAGES/converse.po | 715 ++-- locale/nl/LC_MESSAGES/converse.json | 46 +- locale/nl/LC_MESSAGES/converse.po | 704 ++-- locale/pl/LC_MESSAGES/converse.json | 62 +- locale/pl/LC_MESSAGES/converse.po | 705 ++-- locale/pt_BR/LC_MESSAGES/converse.json | 46 +- locale/pt_BR/LC_MESSAGES/converse.po | 704 ++-- locale/ru/LC_MESSAGES/converse.json | 42 +- locale/ru/LC_MESSAGES/converse.po | 705 ++-- locale/uk/LC_MESSAGES/converse.json | 38 +- locale/uk/LC_MESSAGES/converse.po | 704 ++-- locale/zh/LC_MESSAGES/converse.json | 46 +- locale/zh/LC_MESSAGES/converse.po | 704 ++-- 36 files changed, 9252 insertions(+), 10097 deletions(-) diff --git a/dist/converse-no-dependencies.js b/dist/converse-no-dependencies.js index b3886b75e..bd0701b5c 100644 --- a/dist/converse-no-dependencies.js +++ b/dist/converse-no-dependencies.js @@ -6697,14 +6697,6 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat 'warn': _.get(console, 'log') ? console.log.bind(console) : _.noop }, console); - var afterAnimationEnd = function afterAnimationEnd(el, callback) { - el.classList.remove('visible'); - - if (_.isFunction(callback)) { - callback(); - } - }; - var unescapeHTML = function unescapeHTML(htmlEscapedText) { /* Helper method that replace HTML-escaped symbols with equivalent characters * (e.g. transform occurrences of '&' to '&') @@ -6739,16 +6731,6 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat }); }; - function calculateSlideStep(height) { - if (height > 100) { - return 10; - } else if (height > 50) { - return 5; - } else { - return 1; - } - } - function calculateElementHeight(el) { /* Return the height of the passed in DOM element, * based on the heights of its children. @@ -6768,6 +6750,40 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat var u = {}; + u.removeElement = function (el) { + if (!_.isNil(el) && !_.isNil(el.parentNode)) { + el.parentNode.removeChild(el); + } + }; + + u.showElement = function (el) { + if (!_.isNil(el)) { + el.classList.remove('collapsed'); + el.classList.remove('hidden'); + } + }; + + u.hideElement = function (el) { + if (!_.isNil(el)) { + el.classList.add('hidden'); + } + }; + + u.nextUntil = function (el, selector) { + var include_self = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + /* Return the element's siblings until one matches the selector. */ + var matches = []; + var sibling_el = el.nextElementSibling; + + while (!_.isNil(sibling_el) && !sibling_el.matches(selector)) { + matches.push(sibling_el); + sibling_el = sibling_el.nextElementSibling; + } + + return matches; + }; + u.addHyperlinks = function (text) { var list = text.match(URL_REGEX) || []; var links = []; @@ -6809,7 +6825,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat }; u.slideInAllElements = function (elements) { - return Promise.all(_.map(elements, _.partial(u.slideIn, _, 600))); + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 600; + return Promise.all(_.map(elements, _.partial(u.slideIn, _, duration))); }; u.slideToggleElement = function (el) { @@ -6820,8 +6837,12 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat } }; + u.hasClass = function (el, className) { + return _.includes(el.classList, className); + }; + u.slideOut = function (el) { - var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 900; + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 250; /* Shows/expands an element by sliding it out of itself * @@ -6837,11 +6858,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat return; } - var interval_marker = el.getAttribute('data-slider-marker'); + var marker = el.getAttribute('data-slider-marker'); - if (interval_marker) { + if (marker) { el.removeAttribute('data-slider-marker'); - window.clearInterval(interval_marker); + window.cancelAnimationFrame(marker); } var end_height = calculateElementHeight(el); @@ -6854,30 +6875,43 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat return; } - var step = calculateSlideStep(end_height), - interval = end_height / duration * step; - var h = 0; - interval_marker = window.setInterval(function () { - h += step; + if (!u.hasClass(el, 'collapsed') && !u.hasClass(el, 'hidden')) { + resolve(); + return; + } - if (h < end_height) { - el.style.height = h + 'px'; + var steps = duration / 17; // We assume 17ms per animation which is ~60FPS + + var height = 0; + + function draw() { + height += end_height / steps; + + if (height < end_height) { + el.style.height = height + 'px'; + el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw)); } else { // We recalculate the height to work around an apparent // browser bug where browsers don't know the correct // offsetHeight beforehand. + el.removeAttribute('data-slider-marker'); el.style.height = calculateElementHeight(el) + 'px'; - window.clearInterval(interval_marker); - slideOutWrapup(el); + el.style.overflow = ""; + el.style.height = ""; resolve(); } - }, interval); - el.setAttribute('data-slider-marker', interval_marker); + } + + el.style.height = '0'; + el.style.overflow = 'hidden'; + el.classList.remove('hidden'); + el.classList.remove('collapsed'); + el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw)); }); }; u.slideIn = function (el) { - var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 600; + var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 250; /* Hides/collapses an element by sliding it into itself. */ return new Promise(function (resolve, reject) { @@ -6894,60 +6928,63 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat return resolve(); } - var interval_marker = el.getAttribute('data-slider-marker'); + var marker = el.getAttribute('data-slider-marker'); - if (interval_marker) { + if (marker) { el.removeAttribute('data-slider-marker'); - window.clearInterval(interval_marker); + window.cancelAnimationFrame(marker); } - var h = el.offsetHeight; - var step = calculateSlideStep(h), - interval = h / duration * step; - el.style.overflow = 'hidden'; - interval_marker = window.setInterval(function () { - h -= step; + var original_height = el.offsetHeight, + steps = duration / 17; // We assume 17ms per animation which is ~60FPS - if (h > 0) { - el.style.height = h + 'px'; + var height = original_height; + el.style.overflow = 'hidden'; + + function draw() { + height -= original_height / steps; + + if (height > 0) { + el.style.height = height + 'px'; + el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw)); } else { el.removeAttribute('data-slider-marker'); - window.clearInterval(interval_marker); el.classList.add('collapsed'); el.style.height = ""; resolve(); } - }, interval); - el.setAttribute('data-slider-marker', interval_marker); + } + + el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw)); }); }; + function afterAnimationEnds(el, callback) { + el.classList.remove('visible'); + + if (_.isFunction(callback)) { + callback(); + } + } + u.fadeIn = function (el, callback) { if (_.isNil(el)) { logger.warn("Undefined or null element passed into fadeIn"); } if (window.converse_disable_effects) { - // Effects are disabled (for tests) el.classList.remove('hidden'); - - if (_.isFunction(callback)) { - callback(); - } - - return; + return afterAnimationEnds(el, callback); } if (_.includes(el.classList, 'hidden')) { - /* XXX: This doesn't appear to be working... - el.addEventListener("webkitAnimationEnd", _.partial(afterAnimationEnd, el, callback), false); - el.addEventListener("animationend", _.partial(afterAnimationEnd, el, callback), false); - */ - setTimeout(_.partial(afterAnimationEnd, el, callback), 351); el.classList.add('visible'); el.classList.remove('hidden'); + el.addEventListener("webkitAnimationEnd", _.partial(afterAnimationEnds, el, callback)); + el.addEventListener("animationend", _.partial(afterAnimationEnds, el, callback)); + el.addEventListener("oanimationend", _.partial(afterAnimationEnds, el, callback)); } else { - afterAnimationEnd(el, callback); + afterAnimationEnds(el, callback); } }; @@ -7662,8 +7699,6 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat } else if (level === Strophe.LogLevel.WARN) { if (_converse.debug) { logger.warn("".concat(prefix, " ").concat(moment().format(), " WARNING: ").concat(message), style); - } else { - logger.warn("".concat(prefix, " WARNING: ").concat(message), style); } } else if (level === Strophe.LogLevel.FATAL) { if (_converse.debug) { @@ -7739,7 +7774,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat // out or disconnecting in the previous session. // This happens in tests. We therefore first clean up. Backbone.history.stop(); + + _converse.chatboxviews.closeAllChatBoxes(); + delete _converse.controlboxtoggle; + delete _converse.chatboxviews; _converse.connection.reset(); @@ -8318,7 +8357,11 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat _converse.emit('rosterContactsFetched'); _converse.sendInitialPresence(); - }).catch(_converse.sendInitialPresence); + }).catch(function (reason) { + _converse.log(reason, Strophe.LogLevel.ERROR); + + _converse.sendInitialPresence(); + }); } else { _converse.rostergroups.fetchRosterGroups().then(function () { _converse.emit('rosterGroupsFetched'); @@ -8328,7 +8371,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat _converse.emit('rosterContactsFetched'); _converse.sendInitialPresence(); - }).catch(function () { + }).catch(function (reason) { + _converse.log(reason, Strophe.LogLevel.ERROR); + _converse.sendInitialPresence(); }); } @@ -8687,7 +8732,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat */ return new Promise(function (resolve, reject) { _this4.fetch({ - add: true, + 'add': true, + 'silent': true, success: function success(collection) { if (collection.length === 0) { _converse.send_initial_presence = true; @@ -9084,116 +9130,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat }); } }); - this.Message = Backbone.Model.extend({ - defaults: function defaults() { - return { - msgid: _converse.connection.getUniqueId() - }; - } - }); - this.Messages = Backbone.Collection.extend({ - model: _converse.Message, - comparator: 'time' - }); - this.ChatBox = Backbone.Model.extend({ - defaults: { - 'type': 'chatbox', - 'bookmarked': false, - 'chat_state': undefined, - 'num_unread': 0, - 'url': '' - }, - initialize: function initialize() { - this.messages = new _converse.Messages(); - this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](b64_sha1("converse.messages".concat(this.get('jid')).concat(_converse.bare_jid))); - this.save({ - // The chat_state will be set to ACTIVE once the chat box is opened - // and we listen for change:chat_state, so shouldn't set it to ACTIVE here. - 'box_id': b64_sha1(this.get('jid')), - 'time_opened': this.get('time_opened') || moment().valueOf(), - 'user_id': Strophe.getNodeFromJid(this.get('jid')) - }); - }, - getMessageBody: function getMessageBody(message) { - var type = message.getAttribute('type'); - return type === 'error' ? _.propertyOf(message.querySelector('error text'))('textContent') : _.propertyOf(message.querySelector('body'))('textContent'); - }, - getMessageAttributes: function getMessageAttributes(message, delay, original_stanza) { - delay = delay || message.querySelector('delay'); - var type = message.getAttribute('type'), - body = this.getMessageBody(message); - - var delayed = !_.isNull(delay), - is_groupchat = type === 'groupchat', - chat_state = message.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || message.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || message.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || message.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || message.getElementsByTagName(_converse.GONE).length && _converse.GONE; - - var from; - - if (is_groupchat) { - from = Strophe.unescapeNode(Strophe.getResourceFromJid(message.getAttribute('from'))); - } else { - from = Strophe.getBareJidFromJid(message.getAttribute('from')); - } - - var time = delayed ? delay.getAttribute('stamp') : moment().format(); - var sender, fullname; - - if (is_groupchat && from === this.get('nick') || !is_groupchat && from === _converse.bare_jid) { - sender = 'me'; - fullname = _converse.xmppstatus.get('fullname') || from; - } else { - sender = 'them'; - fullname = this.get('fullname') || from; - } - - return { - 'type': type, - 'chat_state': chat_state, - 'delayed': delayed, - 'fullname': fullname, - 'message': body || undefined, - 'msgid': message.getAttribute('id'), - 'sender': sender, - 'time': time - }; - }, - createMessage: function createMessage(message, delay, original_stanza) { - return this.messages.create(this.getMessageAttributes.apply(this, arguments)); - }, - newMessageWillBeHidden: function newMessageWillBeHidden() { - /* Returns a boolean to indicate whether a newly received - * message will be visible to the user or not. - */ - return this.get('hidden') || this.get('minimized') || this.isScrolledUp() || _converse.windowState === 'hidden'; - }, - incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) { - /* Given a newly received message, update the unread counter if - * necessary. - */ - if (_.isNull(stanza.querySelector('body'))) { - return; // The message has no text - } - - if (utils.isNewMessage(stanza) && this.newMessageWillBeHidden()) { - this.save({ - 'num_unread': this.get('num_unread') + 1 - }); - - _converse.incrementMsgCounter(); - } - }, - clearUnreadMsgCounter: function clearUnreadMsgCounter() { - this.save({ - 'num_unread': 0 - }); - }, - isScrolledUp: function isScrolledUp() { - return this.get('scrolled', true); - } - }); this.ConnectionFeedback = Backbone.Model.extend({ defaults: { - 'connection_status': undefined, + 'connection_status': Strophe.Status.DISCONNECTED, 'message': '' }, initialize: function initialize() { @@ -9368,7 +9307,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat this.connection.restore(this.jid, this.onConnectStatusChanged); return true; } catch (e) { - _converse.log("Could not restore session for jid: " + this.jid + " Error message: " + e.message); + _converse.log("Could not restore session for jid: " + this.jid + " Error message: " + e.message, Strophe.LogLevel.WARN); this.clearSession(); // If there's a roster, we want to clear it (see #555) @@ -9807,6 +9746,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat Promise = _converse$env.Promise, Strophe = _converse$env.Strophe, b64_sha1 = _converse$env.b64_sha1, + moment = _converse$env.moment, utils = _converse$env.utils, _ = _converse$env._; converse.plugins.add('converse-chatboxes', { @@ -9863,6 +9803,113 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat _converse.router.route('converse/chat?jid=:jid', openChat); + _converse.Message = Backbone.Model.extend({ + defaults: function defaults() { + return { + msgid: _converse.connection.getUniqueId() + }; + } + }); + _converse.Messages = Backbone.Collection.extend({ + model: _converse.Message, + comparator: 'time' + }); + _converse.ChatBox = Backbone.Model.extend({ + defaults: { + 'type': 'chatbox', + 'bookmarked': false, + 'chat_state': undefined, + 'num_unread': 0, + 'url': '' + }, + initialize: function initialize() { + this.messages = new _converse.Messages(); + this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](b64_sha1("converse.messages".concat(this.get('jid')).concat(_converse.bare_jid))); + this.save({ + // The chat_state will be set to ACTIVE once the chat box is opened + // and we listen for change:chat_state, so shouldn't set it to ACTIVE here. + 'box_id': b64_sha1(this.get('jid')), + 'time_opened': this.get('time_opened') || moment().valueOf(), + 'user_id': Strophe.getNodeFromJid(this.get('jid')) + }); + }, + getMessageBody: function getMessageBody(message) { + var type = message.getAttribute('type'); + return type === 'error' ? _.propertyOf(message.querySelector('error text'))('textContent') : _.propertyOf(message.querySelector('body'))('textContent'); + }, + getMessageAttributes: function getMessageAttributes(message, delay, original_stanza) { + delay = delay || message.querySelector('delay'); + var type = message.getAttribute('type'), + body = this.getMessageBody(message); + + var delayed = !_.isNull(delay), + is_groupchat = type === 'groupchat', + chat_state = message.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || message.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || message.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || message.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || message.getElementsByTagName(_converse.GONE).length && _converse.GONE; + + var from; + + if (is_groupchat) { + from = Strophe.unescapeNode(Strophe.getResourceFromJid(message.getAttribute('from'))); + } else { + from = Strophe.getBareJidFromJid(message.getAttribute('from')); + } + + var time = delayed ? delay.getAttribute('stamp') : moment().format(); + var sender, fullname; + + if (is_groupchat && from === this.get('nick') || !is_groupchat && from === _converse.bare_jid) { + sender = 'me'; + fullname = _converse.xmppstatus.get('fullname') || from; + } else { + sender = 'them'; + fullname = this.get('fullname') || from; + } + + return { + 'type': type, + 'chat_state': chat_state, + 'delayed': delayed, + 'fullname': fullname, + 'message': body || undefined, + 'msgid': message.getAttribute('id'), + 'sender': sender, + 'time': time + }; + }, + createMessage: function createMessage(message, delay, original_stanza) { + return this.messages.create(this.getMessageAttributes.apply(this, arguments)); + }, + newMessageWillBeHidden: function newMessageWillBeHidden() { + /* Returns a boolean to indicate whether a newly received + * message will be visible to the user or not. + */ + return this.get('hidden') || this.get('minimized') || this.isScrolledUp() || _converse.windowState === 'hidden'; + }, + incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) { + /* Given a newly received message, update the unread counter if + * necessary. + */ + if (_.isNull(stanza.querySelector('body'))) { + return; // The message has no text + } + + if (utils.isNewMessage(stanza) && this.newMessageWillBeHidden()) { + this.save({ + 'num_unread': this.get('num_unread') + 1 + }); + + _converse.incrementMsgCounter(); + } + }, + clearUnreadMsgCounter: function clearUnreadMsgCounter() { + this.save({ + 'num_unread': 0 + }); + }, + isScrolledUp: function isScrolledUp() { + return this.get('scrolled', true); + } + }); _converse.ChatBoxes = Backbone.Collection.extend({ comparator: 'time_opened', model: function model(attrs, options) { @@ -10117,8 +10164,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat }, showChat: function showChat(attrs) { /* Find the chat box and show it (if it may be shown). - * If it doesn't exist, create it. - */ + * If it doesn't exist, create it. + */ var chatbox = this.getChatBox(attrs, true); if (this.chatBoxMayBeShown(chatbox)) { @@ -10354,7 +10401,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ns.imagePathPNG = 'https://cdn.jsdelivr.net/emojione/assets/' + ns.emojiVersion + '/png/'; ns.defaultPathPNG = ns.imagePathPNG; ns.imageTitleTag = true; // set to false to remove title attribute from img tag - ns.sprites = true; // if this is true then sprite markup will be used + ns.sprites = false; // if this is true then sprite markup will be used ns.spriteSize = '32'; ns.unicodeAlt = true; // use the unicode char as the alt attribute (makes copy and pasting the resulting text better) ns.ascii = false; // change to true to convert ascii smileys @@ -12561,15 +12608,19 @@ var __t, __p = '', __e = _.escape, __j = Array.prototype.join; function print() { __p += __j.call(arguments, '') } __p += '
\n \n User Avatar\n '; + if (o.show_avatar) { ; +__p += '\n User Avatar\n
\n '; +'"/>\n '; + } ; +__p += '\n \n'; return __p };}); @@ -12757,8 +12808,8 @@ return __p Strophe = _converse$env.Strophe, _ = _converse$env._, b64_sha1 = _converse$env.b64_sha1, - moment = _converse$env.moment, - utils = _converse$env.utils; + moment = _converse$env.moment; + var u = converse.env.utils; var KEY = { ENTER: 13, FORWARD_SLASH: 47 @@ -12779,7 +12830,7 @@ return __p return; } - utils.slideInAllElements(document.querySelectorAll('.toolbar-menu')); + u.slideInAllElements(document.querySelectorAll('.toolbar-menu')); }); }, ChatBoxViews: { @@ -12859,8 +12910,8 @@ return __p var emojis_html = tpl_emojis(_.extend(this.model.toJSON(), { 'transform': _converse.use_emojione ? emojione.shortnameToImage : emojione.shortnameToUnicode, - 'emojis_by_category': utils.getEmojisByCategory(_converse, emojione), - 'toned_emojis': utils.getTonedEmojis(_converse), + 'emojis_by_category': u.getEmojisByCategory(_converse, emojione), + 'toned_emojis': u.getTonedEmojis(_converse), 'skintones': ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'], 'shouldBeHidden': this.shouldBeHidden })); @@ -12977,7 +13028,8 @@ return __p this.model.on('showHelpMessages', this.showHelpMessages, this); this.model.on('sendMessage', this.sendMessage, this); this.render().renderToolbar().insertHeading().fetchMessages(); - utils.refreshWebkit(); + this.createEmojiPicker(); + u.refreshWebkit(); _converse.emit('chatBoxOpened', this); @@ -13243,20 +13295,24 @@ return __p 'extra_classes': this.getExtraMessageClasses(attrs) }))); var msg_content = $msg[0].querySelector('.chat-msg-content'); - msg_content.innerHTML = utils.addEmoji(_converse, emojione, utils.addHyperlinks(xss.filterXSS(text, { + msg_content.innerHTML = u.addEmoji(_converse, emojione, u.addHyperlinks(xss.filterXSS(text, { 'whiteList': {} }))); - utils.renderImageURLs(msg_content); + u.renderImageURLs(msg_content); return $msg; }, showHelpMessages: function showHelpMessages(msgs, type, spinner) { var _this3 = this; _.each(msgs, function (msg) { - _this3.$content.append($(tpl_help_message({ + _this3.content.insertAdjacentHTML('beforeend', tpl_help_message({ 'type': type || 'info', - 'message': msgs - }))); + 'message': xss.filterXSS(msg, { + 'whiteList': { + 'strong': [] + } + }) + })); }); if (spinner === true) { @@ -13294,14 +13350,14 @@ return __p handleTextMessage: function handleTextMessage(message) { this.showMessage(_.clone(message.attributes)); - if (utils.isNewMessage(message) && message.get('sender') === 'me') { + if (u.isNewMessage(message) && message.get('sender') === 'me') { // We remove the "scrolled" flag so that the chat area // gets scrolled down. We always want to scroll down // when the user writes a message as opposed to when a // message is received. this.model.set('scrolled', false); } else { - if (utils.isNewMessage(message) && this.model.get('scrolled', true)) { + if (u.isNewMessage(message) && this.model.get('scrolled', true)) { this.$el.find('.new-msgs-indicator').removeClass('hidden'); } } @@ -13527,7 +13583,7 @@ return __p var elements = _.difference(document.querySelectorAll('.toolbar-menu'), [this.emoji_picker_view.el]); - utils.slideInAllElements(elements).then(_.partial(utils.slideToggleElement, this.emoji_picker_view.el)).then(this.focus.bind(this)); + u.slideInAllElements(elements).then(_.partial(u.slideToggleElement, this.emoji_picker_view.el)).then(this.focus.bind(this)); }, toggleCall: function toggleCall(ev) { ev.stopPropagation(); @@ -13566,7 +13622,7 @@ return __p if (_converse.connection.connected) { // Immediately sending the chat state, because the // model is going to be destroyed afterwards. - this.model.set('chat_state', _converse.INACTIVE); + this.setChatState(_converse.INACTIVE); this.sendChatState(); } @@ -13600,29 +13656,36 @@ return __p toolbar = toolbar || tpl_toolbar; options = _.assign(this.model.toJSON(), this.getToolbarOptions(options || {})); this.el.querySelector('.chat-toolbar').innerHTML = toolbar(options); + return this; + }, + renderEmojiPicker: function renderEmojiPicker() { var toggle = this.el.querySelector('.toggle-smiley'); toggle.innerHTML = ''; toggle.appendChild(this.emoji_picker_view.render().el); - return this; }, focus: function focus() { - this.el.querySelector('.chat-textarea').focus(); + var textarea_el = this.el.querySelector('.chat-textarea'); - _converse.emit('chatBoxFocused', this); + if (!_.isNull(textarea_el)) { + textarea_el.focus(); + + _converse.emit('chatBoxFocused', this); + } return this; }, hide: function hide() { this.el.classList.add('hidden'); - utils.refreshWebkit(); + u.refreshWebkit(); return this; }, afterShown: function afterShown(focus) { - if (utils.isPersistableModel(this.model)) { + if (u.isPersistableModel(this.model)) { this.model.save(); } this.setChatState(_converse.ACTIVE); + this.renderEmojiPicker(); this.scrollDown(); if (focus) { @@ -13631,7 +13694,7 @@ return __p }, _show: function _show(focus) { /* Inner show method that gets debounced */ - if (this.$el.is(':visible') && this.$el.css('opacity') === "1") { + if (u.isVisible(this.el)) { if (focus) { this.focus(); } @@ -13639,7 +13702,14 @@ return __p return; } - utils.fadeIn(this.el, _.bind(this.afterShown, this, focus)); + var that = this; + u.fadeIn(this.el, function () { + that.afterShown(); + + if (focus) { + that.focus(); + } + }); }, show: function show(focus) { if (_.isUndefined(this.debouncedShow)) { @@ -13689,7 +13759,7 @@ return __p this.onScrolledDown(); } - utils.safeSave(this.model, { + u.safeSave(this.model, { 'scrolled': scrolled }); }, @@ -13699,8 +13769,12 @@ return __p }, _scrollDown: function _scrollDown() { /* Inner method that gets debounced */ - if (this.$content.is(':visible') && !this.model.get('scrolled')) { - this.$content.scrollTop(this.$content[0].scrollHeight); + if (_.isUndefined(this.content)) { + return; + } + + if (u.isVisible(this.content) && !this.model.get('scrolled')) { + this.content.scrollTop = this.content.scrollHeight; this.onScrolledDown(); this.model.save({ 'auto_scrolled': true @@ -13931,14 +14005,19 @@ return __p define('tpl!group_header', ['lodash'], function(_) {return function(o) { -var __t, __p = '', __e = _.escape; +var __t, __p = '', __e = _.escape, __j = Array.prototype.join; +function print() { __p += __j.call(arguments, '') } __p += '' + __e(o.label_group) + -'\n'; +'\n\n'; return __p };}); @@ -13999,7 +14078,7 @@ return __p define('tpl!roster', ['lodash'], function(_) {return function(o) { var __t, __p = ''; -__p += '
\n'; +__p += '
\n'; return __p };}); @@ -14138,18 +14217,18 @@ return __p /*global define */ (function (root, factory) { - define('converse-rosterview',["jquery.noconflict", "converse-core", "tpl!group_header", "tpl!pending_contact", "tpl!requesting_contact", "tpl!roster", "tpl!roster_filter", "tpl!roster_item", "converse-chatboxes"], factory); -})(this, function ($, converse, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item) { + define('converse-rosterview',["converse-core", "tpl!group_header", "tpl!pending_contact", "tpl!requesting_contact", "tpl!roster", "tpl!roster_filter", "tpl!roster_item", "converse-chatboxes"], factory); +})(this, function (converse, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item) { "use strict"; var _converse$env = converse.env, Backbone = _converse$env.Backbone, - utils = _converse$env.utils, Strophe = _converse$env.Strophe, $iq = _converse$env.$iq, b64_sha1 = _converse$env.b64_sha1, sizzle = _converse$env.sizzle, _ = _converse$env._; + var u = converse.env.utils; converse.plugins.add('converse-rosterview', { overrides: { // Overrides mentioned here will be picked up by converse.js's @@ -14269,7 +14348,7 @@ return __p this.model.on('change:filter_type', this.render, this); this.model.on('change:filter_text', this.renderClearButton, this); }, - renderHTML: function renderHTML() { + toHTML: function toHTML() { return tpl_roster_filter(_.extend(this.model.toJSON(), { visible: this.shouldBeVisible(), placeholder: __('Filter'), @@ -14372,7 +14451,7 @@ return __p } }, show: function show() { - if (utils.isVisible(this.el)) { + if (u.isVisible(this.el)) { return this; } @@ -14381,7 +14460,7 @@ return __p return this; }, hide: function hide() { - if (!utils.isVisible(this.el)) { + if (!u.isVisible(this.el)) { return this; } @@ -14409,7 +14488,9 @@ return __p tagName: 'div', id: 'converse-roster', initialize: function initialize() { - _converse.roster.on("add", this.onContactAdd, this); + var _this = this; + + _converse.roster.on("add", this.onContactAdded, this); _converse.roster.on('change', this.onContactChange, this); @@ -14417,19 +14498,23 @@ return __p _converse.roster.on("remove", this.update, this); - this.model.on("add", this.onGroupAdd, this); + this.model.on("add", this.onGroupAdded, this); this.model.on("reset", this.reset, this); _converse.on('rosterGroupsFetched', this.positionFetchedGroups, this); - _converse.on('rosterContactsFetched', this.update, this); + _converse.on('rosterContactsFetched', function () { + _converse.roster.each(_this.onContactAdded.bind(_this)); + + _this.update(); + }); this.createRosterFilter(); }, render: function render() { - this.renderRoster(); this.el.innerHTML = ""; this.el.appendChild(this.filter_view.render().el); + this.renderRoster(); if (!_converse.allow_contact_requests) { // XXX: if we ever support live editing of config then @@ -14440,8 +14525,10 @@ return __p return this; }, renderRoster: function renderRoster() { - this.$roster = $(tpl_roster()); - this.roster = this.$roster[0]; + var div = document.createElement('div'); + div.insertAdjacentHTML('beforeend', tpl_roster()); + this.roster_el = div.firstChild; + this.el.insertAdjacentElement('beforeend', this.roster_el); }, createRosterFilter: function createRosterFilter() { // Create a model on which we can store filter properties @@ -14471,14 +14558,14 @@ return __p } }, 100), update: _.debounce(function () { - if (_.isNull(this.roster.parentElement)) { - this.$el.append(this.$roster.show()); + if (!u.isVisible(this.roster_el)) { + u.showElement(this.roster_el); } return this.showHideFilter(); }, _converse.animate ? 100 : 0), showHideFilter: function showHideFilter() { - if (!utils.isVisible(this.el)) { + if (!u.isVisible(this.el)) { return; } @@ -14500,9 +14587,9 @@ return __p if (type === 'groups') { _.each(this.getAll(), function (view, idx) { if (!_.includes(view.model.get('name').toLowerCase(), query.toLowerCase())) { - view.hide(); + u.slideIn(view.el); } else if (view.model.contacts.length > 0) { - view.show(); + u.slideOut(view.el); } }); } else { @@ -14515,18 +14602,17 @@ return __p _converse.roster.reset(); this.removeAll(); - this.renderRoster(); this.render().update(); return this; }, - onGroupAdd: function onGroupAdd(group) { + onGroupAdded: function onGroupAdded(group) { var view = new _converse.RosterGroupView({ model: group }); - this.add(group.get('name'), view.render()); - this.positionGroup(view); + this.add(group.get('name'), view); + this.positionGroup(group); }, - onContactAdd: function onContactAdd(contact) { + onContactAdded: function onContactAdded(contact) { this.addRosterContact(contact).update(); this.updateFilter(); }, @@ -14579,52 +14665,28 @@ return __p * positioned aren't already in inserted into the * roster DOM element. */ - var that = this; this.model.sort(); - this.model.each(function (group, idx) { - var view = that.get(group.get('name')); - - if (!view) { - view = new _converse.RosterGroupView({ - model: group - }); - that.add(group.get('name'), view.render()); - } - - if (idx === 0) { - that.$roster.append(view.$el); - } else { - that.appendGroup(view); - } - }); + this.model.each(this.onGroupAdded.bind(this)); }, - positionGroup: function positionGroup(view) { + positionGroup: function positionGroup(group) { /* Place the group's DOM element in the correct alphabetical * position amongst the other groups in the roster. + * + * NOTE: relies on the assumption that it will be called in + * the right order of appearance of groups. */ - var $groups = this.$roster.find('.roster-group'), - index = $groups.length ? this.model.indexOf(view.model) : 0; + var view = this.get(group.get('name')); + view.render(); + var list = this.roster_el, + index = this.model.indexOf(view.model); if (index === 0) { - this.$roster.prepend(view.$el); + list.insertAdjacentElement('afterbegin', view.el); } else if (index === this.model.length - 1) { - this.appendGroup(view); + list.insertAdjacentElement('beforeend', view.el); } else { - $($groups.eq(index)).before(view.$el); - } - - return this; - }, - appendGroup: function appendGroup(view) { - /* Add the group at the bottom of the roster - */ - var $last = this.$roster.find('.roster-group').last(); - var $siblings = $last.siblings('dd'); - - if ($siblings.length > 0) { - $siblings.last().after(view.$el); - } else { - $last.after(view.$el); + var neighbour_el = list.querySelector('div:nth-child(' + index + ')'); + neighbour_el.insertAdjacentElement('afterend', view.el); } return this; @@ -14677,7 +14739,8 @@ return __p } }); _converse.RosterContactView = Backbone.View.extend({ - tagName: 'dd', + tagName: 'li', + className: 'hidden', events: { "click .accept-xmpp-request": "acceptRequest", "click .decline-xmpp-request": "declineRequest", @@ -14694,7 +14757,7 @@ return __p var that = this; if (!this.mayBeShown()) { - this.$el.hide(); + u.hideElement(this.el); return this; } @@ -14711,7 +14774,8 @@ return __p } }); - this.$el.addClass(chat_status).data('status', chat_status); + this.el.classList.add(chat_status); + this.el.setAttribute('data-status', chat_status); if (ask === 'subscribe' || subscription === 'from') { /* ask === 'subscribe' @@ -14726,17 +14790,17 @@ return __p * So in both cases the user is a "pending" contact. */ this.el.classList.add('pending-xmpp-contact'); - this.$el.html(tpl_pending_contact(_.extend(item.toJSON(), { + this.el.innerHTML = tpl_pending_contact(_.extend(item.toJSON(), { 'desc_remove': __('Click to remove %1$s as a contact', item.get('fullname')), 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts - }))); + })); } else if (requesting === true) { this.el.classList.add('requesting-xmpp-contact'); - this.$el.html(tpl_requesting_contact(_.extend(item.toJSON(), { + this.el.innerHTML = tpl_requesting_contact(_.extend(item.toJSON(), { 'desc_accept': __("Click to accept the contact request from %1$s", item.get('fullname')), 'desc_decline': __("Click to decline the contact request from %1$s", item.get('fullname')), 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts - }))); + })); } else if (subscription === 'both' || subscription === 'to') { this.el.classList.add('current-xmpp-contact'); this.el.classList.remove(_.without(['both', 'to'], subscription)[0]); @@ -14747,45 +14811,22 @@ return __p return this; }, renderRosterItem: function renderRosterItem(item) { - var chat_status = item.get('chat_status'); - this.$el.html(tpl_roster_item(_.extend(item.toJSON(), { - 'desc_status': STATUSES[chat_status || 'offline'], + this.el.innerHTML = tpl_roster_item(_.extend(item.toJSON(), { + 'desc_status': STATUSES[item.get('chat_status') || 'offline'], 'desc_chat': __('Click to chat with this contact'), 'desc_remove': __('Click to remove %1$s as a contact', item.get('fullname')), 'title_fullname': __('Name'), 'allow_contact_removal': _converse.allow_contact_removal, 'num_unread': item.get('num_unread') || 0 - }))); - return this; - }, - isGroupCollapsed: function isGroupCollapsed() { - /* Check whether the group in which this contact appears is - * collapsed. - */ - // XXX: this sucks and is fragile. - // It's because I tried to do the "right thing" - // and use definition lists to represent roster groups. - // If roster group items were inside the group elements, we - // would simplify things by not having to check whether the - // group is collapsed or not. - var name = this.$el.prevAll('dt:first').data('group'); - - var group = _.head(_converse.rosterview.model.where({ - 'name': name.toString() })); - - if (group.get('state') === _converse.CLOSED) { - return true; - } - - return false; + return this; }, mayBeShown: function mayBeShown() { /* Return a boolean indicating whether this contact should * generally be visible in the roster. * * It doesn't check for the more specific case of whether - * the group it's in is collapsed (see isGroupCollapsed). + * the group it's in is collapsed. */ var chatStatus = this.model.get('chat_status'); @@ -14808,7 +14849,7 @@ return __p return _converse.chatboxviews.showChat(this.model.attributes, true); }, removeContact: function removeContact(ev) { - var _this = this; + var _this2 = this; if (ev && ev.preventDefault) { ev.preventDefault(); @@ -14831,9 +14872,9 @@ return __p }); _converse.connection.sendIQ(iq, function (iq) { - _this.model.destroy(); + _this2.model.destroy(); - _this.remove(); + _this2.remove(); }, function (err) { alert(__('Sorry, there was an error while trying to remove %1$s as a contact.', name)); @@ -14842,14 +14883,14 @@ return __p } }, acceptRequest: function acceptRequest(ev) { - var _this2 = this; + var _this3 = this; if (ev && ev.preventDefault) { ev.preventDefault(); } _converse.roster.sendContactAddIQ(this.model.get('jid'), this.model.get('fullname'), [], function () { - _this2.model.authorize().subscribe(); + _this3.model.authorize().subscribe(); }); }, declineRequest: function declineRequest(ev) { @@ -14867,21 +14908,17 @@ return __p } }); _converse.RosterGroupView = Backbone.Overview.extend({ - tagName: 'dt', + tagName: 'div', className: 'roster-group', events: { "click a.group-toggle": "toggle" }, initialize: function initialize() { - this.model.contacts.on("add", this.addContact, this); + this.sortEventually = _.debounce(this.sortAndPositionAll, 500); + this.model.contacts.on("add", this.onContactAdded, this); this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this); this.model.contacts.on("change:requesting", this.onContactRequestChange, this); - this.model.contacts.on("change:chat_status", function (contact) { - // This might be optimized by instead of first sorting, - // finding the correct position in positionContact - this.model.contacts.sort(); - this.positionContact(contact).render(); - }, this); + this.model.contacts.on("change:chat_status", this.sortEventually, this); this.model.contacts.on("destroy", this.onRemove, this); this.model.contacts.on("remove", this.onRemove, this); @@ -14889,34 +14926,33 @@ return __p }, render: function render() { this.el.setAttribute('data-group', this.model.get('name')); - var html = tpl_group_header({ - label_group: this.model.get('name'), - desc_group_toggle: this.model.get('description'), - toggle_state: this.model.get('state') + this.el.innerHTML = tpl_group_header({ + 'label_group': this.model.get('name'), + 'desc_group_toggle': this.model.get('description'), + 'toggle_state': this.model.get('state'), + '_converse': _converse }); - this.el.innerHTML = html; + this.contacts_el = this.el.querySelector('.roster-group-contacts'); return this; }, - addContact: function addContact(contact) { - var view = new _converse.RosterContactView({ + createContactView: function createContactView(contact) { + var contact_view = new _converse.RosterContactView({ model: contact }); - this.add(contact.get('id'), view); - view = this.positionContact(contact).render(); + this.add(contact.get('id'), contact_view); + contact_view.render(); + return contact_view; + }, + onContactAdded: function onContactAdded(contact) { + var contact_view = this.positionContact(contact); - if (view.mayBeShown()) { + if (contact_view.mayBeShown()) { if (this.model.get('state') === _converse.CLOSED) { - if (view.$el[0].style.display !== "none") { - view.$el.hide(); - } - - if (!this.$el.is(':visible')) { - this.$el.show(); - } + u.hideElement(contact_view.el); + u.showElement(this.el); } else { - if (this.$el[0].style.display !== "block") { - this.show(); - } + u.showElement(contact_view.el); + u.showElement(this.el); } } }, @@ -14924,120 +14960,134 @@ return __p /* Place the contact's DOM element in the correct alphabetical * position amongst the other contacts in this group. */ - var view = this.get(contact.get('id')); + var view = this.get(contact.get('id')) || this.createContactView(contact); + var list = this.contacts_el; var index = this.model.contacts.indexOf(contact); - view.$el.detach(); if (index === 0) { - this.$el.after(view.$el); + list.insertAdjacentElement('afterbegin', view.el); } else if (index === this.model.contacts.length - 1) { - this.$el.nextUntil('dt').last().after(view.$el); + list.insertAdjacentElement('beforeend', view.el); } else { - this.$el.nextUntil('dt').eq(index).before(view.$el); + var neighbour_el = list.querySelector('li:nth-child(' + index + ')'); + neighbour_el.insertAdjacentElement('afterend', view.el); } return view; }, + sortAndPositionAll: function sortAndPositionAll() { + this.model.contacts.sort(); + this.model.contacts.each(this.positionContact.bind(this)); + }, show: function show() { - this.$el.show(); + var _this4 = this; - _.each(this.getAll(), function (view) { - if (view.mayBeShown() && !view.isGroupCollapsed()) { - view.$el.show(); + u.showElement(this.el); + + _.each(this.getAll(), function (contact_view) { + if (contact_view.mayBeShown() && _this4.model.get('state') === _converse.OPENED) { + u.showElement(contact_view.el); } }); return this; }, - hide: function hide() { - this.$el.nextUntil('dt').addBack().hide(); + collapse: function collapse() { + return u.slideIn(this.contacts_el); + }, + filterOutContacts: function filterOutContacts() { + var _this5 = this; + + var contacts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + + /* Given a list of contacts, make sure they're filtered out + * (aka hidden) and that all other contacts are visible. + * + * If all contacts are hidden, then also hide the group + * title. + */ + var shown = 0; + var all_contact_views = this.getAll(); + + _.each(this.model.contacts.models, function (contact) { + var contact_view = _this5.get(contact.get('id')); + + if (_.includes(contacts, contact)) { + u.hideElement(contact_view.el); + } else if (contact_view.mayBeShown()) { + u.showElement(contact_view.el); + shown += 1; + } + }); + + if (shown) { + u.showElement(this.el); + } else { + u.hideElement(this.el); + } + }, + getFilterMatches: function getFilterMatches(q, type) { + /* Given the filter query "q" and the filter type "type", + * return a list of contacts that need to be filtered out. + */ + if (q.length === 0) { + return []; + } + + var matches; + q = q.toLowerCase(); + + if (type === 'state') { + if (this.model.get('name') === HEADER_REQUESTING_CONTACTS) { + // When filtering by chat state, we still want to + // show requesting contacts, even though they don't + // have the state in question. + matches = this.model.contacts.filter(function (contact) { + return u.contains.not('chat_status', q)(contact) && !contact.get('requesting'); + }); + } else if (q === 'unread_messages') { + matches = this.model.contacts.filter({ + 'num_unread': 0 + }); + } else { + matches = this.model.contacts.filter(u.contains.not('chat_status', q)); + } + } else { + matches = this.model.contacts.filter(u.contains.not('fullname', q)); + } + + return matches; }, filter: function filter(q, type) { - var _this3 = this; - /* Filter the group's contacts based on the query "q". * The query is matched against the contact's full name. * If all contacts are filtered out (i.e. hidden), then the * group must be filtered out as well. */ - var matches; - - if (q.length === 0) { - if (this.model.get('state') === _converse.OPENED) { - this.model.contacts.each(function (item) { - var view = _this3.get(item.get('id')); - - if (view.mayBeShown() && !view.isGroupCollapsed()) { - view.$el.show(); - } - }); - } - - this.showIfNecessary(); - } else { - q = q.toLowerCase(); - - if (type === 'state') { - if (this.model.get('name') === HEADER_REQUESTING_CONTACTS) { - // When filtering by chat state, we still want to - // show requesting contacts, even though they don't - // have the state in question. - matches = this.model.contacts.filter(function (contact) { - return utils.contains.not('chat_status', q)(contact) && !contact.get('requesting'); - }); - } else if (q === 'unread_messages') { - matches = this.model.contacts.filter({ - 'num_unread': 0 - }); - } else { - matches = this.model.contacts.filter(utils.contains.not('chat_status', q)); - } - } else { - matches = this.model.contacts.filter(utils.contains.not('fullname', q)); - } - - if (matches.length === this.model.contacts.length) { - // hide the whole group - this.hide(); - } else { - _.each(matches, function (item) { - _this3.get(item.get('id')).$el.hide(); - }); - - if (this.model.get('state') === _converse.OPENED) { - _.each(this.model.contacts.reject(utils.contains.not('fullname', q)), function (item) { - _this3.get(item.get('id')).$el.show(); - }); - } - - this.showIfNecessary(); - } - } - }, - showIfNecessary: function showIfNecessary() { - if (!this.$el.is(':visible') && this.model.contacts.length > 0) { - this.$el.show(); - } + this.filterOutContacts(this.getFilterMatches(q, type)); }, toggle: function toggle(ev) { if (ev && ev.preventDefault) { ev.preventDefault(); } - var $el = $(ev.target); - - if ($el.hasClass("icon-opened")) { - this.$el.nextUntil('dt').slideUp(); + if (_.includes(ev.target.classList, "icon-opened")) { this.model.save({ state: _converse.CLOSED }); - $el.removeClass("icon-opened").addClass("icon-closed"); + this.collapse().then(function () { + ev.target.classList.remove("icon-opened"); + ev.target.classList.add("icon-closed"); + }); } else { - $el.removeClass("icon-closed").addClass("icon-opened"); + ev.target.classList.remove("icon-closed"); + ev.target.classList.add("icon-opened"); this.model.save({ state: _converse.OPENED }); - this.filter(_converse.rosterview.$('.roster-filter').val() || '', _converse.rosterview.$('.filter-type').val()); + this.filter(_converse.rosterview.el.querySelector('.roster-filter').value, _converse.rosterview.el.querySelector('.filter-type').value); + u.showElement(this.el); + u.slideOut(this.contacts_el); } }, onContactGroupChange: function onContactGroupChange(contact) { @@ -15049,7 +15099,7 @@ return __p if (in_this_group && !in_this_overview) { this.model.contacts.remove(cid); } else if (!in_this_group && in_this_overview) { - this.addContact(contact); + this.onContactAdded(contact); } }, onContactSubscriptionChange: function onContactSubscriptionChange(contact) { @@ -15076,7 +15126,7 @@ return __p this.remove(contact.get('id')); if (this.model.contacts.length === 0) { - this.$el.hide(); + u.hideElement(this.el); } } }); @@ -15115,7 +15165,7 @@ return __p return; // The message has no text } - if (chatbox.get('type') !== 'chatroom' && utils.isNewMessage(data.stanza) && chatbox.newMessageWillBeHidden()) { + if (chatbox.get('type') !== 'chatroom' && u.isNewMessage(data.stanza) && chatbox.newMessageWillBeHidden()) { var contact = _.head(_converse.roster.where({ 'jid': chatbox.get('jid') })); @@ -15609,8 +15659,8 @@ return __p /*global define */ (function (root, factory) { - define('converse-controlbox',["jquery.noconflict", "converse-core", "lodash.fp", "tpl!add_contact_dropdown", "tpl!add_contact_form", "tpl!converse_brand_heading", "tpl!contacts_panel", "tpl!contacts_tab", "tpl!controlbox", "tpl!controlbox_toggle", "tpl!login_panel", "tpl!search_contact", "tpl!spinner", "converse-chatview", "converse-rosterview", "converse-profile"], factory); -})(this, function ($, converse, fp, tpl_add_contact_dropdown, tpl_add_contact_form, tpl_brand_heading, tpl_contacts_panel, tpl_contacts_tab, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel, tpl_search_contact, tpl_spinner) { + define('converse-controlbox',["jquery.noconflict", "converse-core", "lodash.fp", "tpl!add_contact_dropdown", "tpl!add_contact_form", "tpl!converse_brand_heading", "tpl!contacts_panel", "tpl!contacts_tab", "tpl!controlbox", "tpl!controlbox_toggle", "tpl!login_panel", "tpl!search_contact", "converse-chatview", "converse-rosterview", "converse-profile"], factory); +})(this, function ($, converse, fp, tpl_add_contact_dropdown, tpl_add_contact_form, tpl_brand_heading, tpl_contacts_panel, tpl_contacts_tab, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel, tpl_search_contact) { "use strict"; var USERS_PANEL_ID = 'users'; @@ -16043,7 +16093,7 @@ return __p this.model.on('change', this.render, this); this.listenTo(_converse.connfeedback, 'change', this.render); }, - renderHTML: function renderHTML() { + toHTML: function toHTML() { var connection_status = _converse.connfeedback.get('connection_status'); var feedback_class, pretty_status; @@ -16747,9 +16797,9 @@ __p += '\n \n '; if (o.show_send_button) { ; __p += '\n