diff --git a/dev.html b/dev.html
index 8a73c6460..90522d981 100644
--- a/dev.html
+++ b/dev.html
@@ -64,8 +64,8 @@
'discuss@conference.conversejs.org'
],
auto_reconnect: true,
- // bosh_service_url: 'http://chat.example.org:5280/http-bind/',
- bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
+ bosh_service_url: 'http://chat.example.org:5280/http-bind/',
+ // bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
message_archiving: 'always',
show_controlbox_by_default: true,
strict_plugin_dependencies: false,
diff --git a/spec/minchats.js b/spec/minchats.js
index 25882388c..5d4b240ff 100644
--- a/spec/minchats.js
+++ b/spec/minchats.js
@@ -63,9 +63,13 @@
expect(_converse.minimized_chats.$('.minimized-chats-flyout').is(':visible')).toBeTruthy();
expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeFalsy();
_converse.minimized_chats.$('#toggle-minimized-chats').click();
- expect(_converse.minimized_chats.$('.minimized-chats-flyout').is(':visible')).toBeFalsy();
- expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
- done();
+
+ return test_utils.waitUntil(function () {
+ return _converse.minimized_chats.$('.minimized-chats-flyout').is(':visible');
+ }, 500).then(function () {
+ expect(_converse.minimized_chats.toggleview.model.get('collapsed')).toBeTruthy();
+ done();
+ });
}));
it("shows the number messages received to minimized chats",
diff --git a/src/converse-minimize.js b/src/converse-minimize.js
index f0eaf4564..5f283d1d4 100644
--- a/src/converse-minimize.js
+++ b/src/converse-minimize.js
@@ -7,8 +7,7 @@
/*global define, window */
(function (root, factory) {
- define(["jquery.noconflict",
- "converse-core",
+ define(["converse-core",
"tpl!chatbox_minimize",
"tpl!toggle_chats",
"tpl!trimmed_chat",
@@ -16,7 +15,6 @@
"converse-chatview"
], factory);
}(this, function (
- $,
converse,
tpl_chatbox_minimize,
tpl_toggle_chats,
@@ -25,7 +23,8 @@
) {
"use strict";
- const { _ , utils, Backbone, Promise, Strophe, b64_sha1, moment } = converse.env;
+ const { _ , Backbone, Promise, Strophe, b64_sha1, moment } = converse.env;
+ const u = converse.env.utils;
converse.plugins.add('converse-minimize', {
/* Optional dependencies are other plugins which might be
@@ -55,7 +54,7 @@
registerGlobalEventHandlers () {
const { _converse } = this.__super__;
- $(window).on("resize", _.debounce(function (ev) {
+ window.addEventListener("resize", _.debounce(function (ev) {
if (_converse.connection.connected) {
_converse.chatboxviews.trimChats();
}
@@ -76,14 +75,14 @@
},
maximize () {
- utils.safeSave(this, {
+ u.safeSave(this, {
'minimized': false,
'time_opened': moment().valueOf()
});
},
minimize () {
- utils.safeSave(this, {
+ u.safeSave(this, {
'minimized': true,
'time_minimized': moment().format()
});
@@ -224,8 +223,8 @@
},
getChatBoxWidth (view) {
- if (!view.model.get('minimized') && view.$el.is(':visible')) {
- return view.$el.outerWidth(true);
+ if (!view.model.get('minimized') && u.isVisible(view.el)) {
+ return u.getOuterWidth(view.el, true);
}
return 0;
},
@@ -237,7 +236,7 @@
// the 'closed' state.
!view.model.get('minimized') &&
!view.model.get('closed') &&
- view.$el.is(':visible')
+ u.isVisible(view.el)
);
},
@@ -249,39 +248,45 @@
* another chat box. Otherwise it minimizes the oldest chat box
* to create space.
*/
- const { _converse } = this.__super__;
- const shown_chats = this.getShownChats();
+ const { _converse } = this.__super__,
+ shown_chats = this.getShownChats(),
+ body_width = u.getOuterWidth(document.querySelector('body'), true);
+
if (_converse.no_trimming || shown_chats.length <= 1) {
return;
}
- if (this.getChatBoxWidth(shown_chats[0]) === $('body').outerWidth(true)) {
+ if (this.getChatBoxWidth(shown_chats[0]) === body_width) {
// If the chats shown are the same width as the body,
// then we're in responsive mode and the chats are
// fullscreen. In this case we don't trim.
return;
}
_converse.api.waitUntil('minimizedChatsInitialized').then(() => {
- const $minimized = _.get(_converse.minimized_chats, '$el'),
- minimized_width = _.includes(this.model.pluck('minimized'), true) ? $minimized.outerWidth(true) : 0,
- new_id = newchat ? newchat.model.get('id') : null;
+ const minimized_el = _.get(_converse.minimized_chats, 'el'),
+ new_id = newchat ? newchat.model.get('id') : null;
- const boxes_width = _.reduce(
- this.xget(new_id),
- (memo, view) => memo + this.getChatBoxWidth(view),
- newchat ? newchat.$el.outerWidth(true) : 0);
+ if (minimized_el) {
+ const minimized_width = _.includes(this.model.pluck('minimized'), true) ?
+ u.getOuterWidth(minimized_el, true) : 0;
- if ((minimized_width + boxes_width) > $('body').outerWidth(true)) {
- const oldest_chat = this.getOldestMaximizedChat([new_id]);
- if (oldest_chat) {
- // We hide the chat immediately, because waiting
- // for the event to fire (and letting the
- // ChatBoxView hide it then) causes race
- // conditions.
- const view = this.get(oldest_chat.get('id'));
- if (view) {
- view.hide();
+ const boxes_width = _.reduce(
+ this.xget(new_id),
+ (memo, view) => memo + this.getChatBoxWidth(view),
+ newchat ? u.getOuterWidth(newchat.el, true) : 0
+ );
+ if ((minimized_width + boxes_width) > body_width) {
+ const oldest_chat = this.getOldestMaximizedChat([new_id]);
+ if (oldest_chat) {
+ // We hide the chat immediately, because waiting
+ // for the event to fire (and letting the
+ // ChatBoxView hide it then) causes race
+ // conditions.
+ const view = this.get(oldest_chat.get('id'));
+ if (view) {
+ view.hide();
+ }
+ oldest_chat.minimize();
}
- oldest_chat.minimize();
}
}
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
@@ -344,12 +349,13 @@
);
if (this.model.get('type') === 'chatroom') {
data.title = this.model.get('name');
- this.$el.addClass('chat-head-chatroom');
+ u.addClass(this.el, 'chat-head-chatroom');
} else {
data.title = this.model.get('fullname');
- this.$el.addClass('chat-head-chatbox');
+ u.addClass(this.el, 'chat-head-chatbox');
}
- return this.$el.html(tpl_trimmed_chat(data));
+ this.el.innerHTML = tpl_trimmed_chat(data);
+ return this.el;
},
close (ev) {
@@ -401,11 +407,11 @@
}
if (this.keys().length === 0) {
this.el.classList.add('hidden');
- } else if (this.keys().length > 0 && !this.$el.is(':visible')) {
+ } else if (this.keys().length > 0 && !u.isVisible(this.el)) {
this.el.classList.remove('hidden');
_converse.chatboxviews.trimChats();
}
- return this.$el;
+ return this.el;
},
tearDown () {
@@ -429,7 +435,7 @@
toggle (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); }
this.toggleview.model.save({'collapsed': !this.toggleview.model.get('collapsed')});
- this.$('.minimized-chats-flyout').toggle();
+ u.slideToggleElement(this.el.querySelector('.minimized-chats-flyout'), 200);
},
onChanged (item) {
@@ -444,28 +450,24 @@
}
},
+ addChatView (item) {
+ const existing = this.get(item.get('id'));
+ if (existing && existing.el.parentNode) {
+ return;
+ }
+ const view = new _converse.MinimizedChatBoxView({model: item});
+ this.el.querySelector('.minimized-chats-flyout').insertAdjacentElement('beforeEnd', view.render());
+ this.add(item.get('id'), view);
+ },
+
addMultipleChats (items) {
- _.each(items, (item) => {
- const existing = this.get(item.get('id'));
- if (existing && existing.$el.parent().length !== 0) {
- return;
- }
- const view = new _converse.MinimizedChatBoxView({model: item});
- this.$('.minimized-chats-flyout').append(view.render());
- this.add(item.get('id'), view);
- });
+ _.each(items, this.addChatView.bind(this));
this.toggleview.model.set({'num_minimized': this.keys().length});
this.render();
},
addChat (item) {
- const existing = this.get(item.get('id'));
- if (existing && existing.$el.parent().length !== 0) {
- return;
- }
- const view = new _converse.MinimizedChatBoxView({model: item});
- this.$('.minimized-chats-flyout').append(view.render());
- this.add(item.get('id'), view);
+ this.addChatView(item);
this.toggleview.model.set({'num_minimized': this.keys().length});
this.render();
},
@@ -501,21 +503,21 @@
initialize () {
this.model.on('change:num_minimized', this.render, this);
this.model.on('change:num_unread', this.render, this);
- this.$flyout = this.$el.siblings('.minimized-chats-flyout');
+ this.flyout = this.el.parentElement.querySelector('.minimized-chats-flyout');
},
render () {
- this.$el.html(tpl_toggle_chats(
+ this.el.innerHTML = tpl_toggle_chats(
_.extend(this.model.toJSON(), {
'Minimized': __('Minimized')
})
- ));
+ );
if (this.model.get('collapsed')) {
- this.$flyout.hide();
+ u.hideElement(this.flyout);
} else {
- this.$flyout.show();
+ u.showElement(this.flyout);
}
- return this.$el;
+ return this.el;
}
});
@@ -531,14 +533,16 @@
_converse.on('chatBoxOpened', function renderMinimizeButton (view) {
// Inserts a "minimize" button in the chatview's header
- const $el = view.$el.find('.toggle-chatbox-button');
- const $new_el = tpl_chatbox_minimize(
+ const new_html = tpl_chatbox_minimize(
{info_minimize: __('Minimize this chat box')}
);
- if ($el.length) {
- $el.replaceWith($new_el);
+
+ const el = view.el.querySelector('.toggle-chatbox-button');
+ if (el) {
+ el.outerHTML = new_html;
} else {
- view.$el.find('.close-chatbox-button').after($new_el);
+ const button = view.el.querySelector('.close-chatbox-button');
+ button.insertAdjacentHTML('afterEnd', new_html);
}
});
diff --git a/src/converse-otr.js b/src/converse-otr.js
index c664db4ff..55c2d00d6 100644
--- a/src/converse-otr.js
+++ b/src/converse-otr.js
@@ -389,10 +389,7 @@
[menu]
);
utils.slideInAllElements(elements).then(
- _.partial(
- utils.slideToggleElement,
- menu
- )
+ _.partial(utils.slideToggleElement, menu)
);
},
diff --git a/src/utils.js b/src/utils.js
index aaadb3f2d..b3f98e311 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -87,8 +87,14 @@
var u = {};
+ u.addClass = function (el, className) {
+ if (el instanceof Element) {
+ el.classList.add(className);
+ }
+ }
+
u.removeClass = function (klass, el) {
- if (!_.isNil(el)) {
+ if (el instanceof Element) {
el.classList.remove(klass);
}
return el;
@@ -163,11 +169,12 @@
));
};
- u.slideToggleElement = function (el) {
- if (_.includes(el.classList, 'collapsed')) {
- return u.slideOut(el);
+ u.slideToggleElement = function (el, duration) {
+ if (_.includes(el.classList, 'collapsed') ||
+ _.includes(el.classList, 'hidden')) {
+ return u.slideOut(el, duration);
} else {
- return u.slideIn(el);
+ return u.slideIn(el, duration);
}
};
@@ -331,9 +338,10 @@
* message, i.e. not a MAM archived one.
*/
if (message instanceof Element) {
- return !(sizzle('result[xmlns="'+Strophe.NS.MAM+'"]', message).length);
+ return !sizzle('result[xmlns="'+Strophe.NS.MAM+'"]', message).length &&
+ !sizzle('delay[xmlns="'+Strophe.NS.DELAY+'"]', message).length;
} else {
- return !message.get('archive_id');
+ return !message.get('archive_id') && !message.get('delayed');
}
};
@@ -415,6 +423,16 @@
return div.firstChild;
};
+ u.getOuterWidth = function (el, include_margin=false) {
+ var width = el.offsetWidth;
+ if (!include_margin) {
+ return width;
+ }
+ var style = window.getComputedStyle(el);
+ width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
+ return width;
+ };
+
u.stringToElement = function (s) {
/* Converts an HTML string into a DOM element.
* Expects that the HTML string has only one top-level element,