diff --git a/spec/chatbox.js b/spec/chatbox.js index cf1833229..39b198f90 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -1612,8 +1612,8 @@ expect(view.sendMessage).toHaveBeenCalled(); var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); expect(msg.html()).toEqual( - ''); + ''); message += "?param1=val1¶m2=val2"; test_utils.sendMessage(view, message); return test_utils.waitUntil(function () { @@ -1623,9 +1623,8 @@ expect(view.sendMessage).toHaveBeenCalled(); var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); expect(msg.html()).toEqual( - '') + '') // Test now with two images in one message message += ' hello world '+base_url+"/logo/conversejs.svg"; @@ -1638,9 +1637,9 @@ var msg = $(view.el).find('.chat-content').find('.chat-message').last().find('.chat-msg-content'); expect(msg.html()).toEqual( ''+ - ' hello world '+ + ' hello world '+ ''+ - '' + '' ) done(); }); diff --git a/src/converse-chatview.js b/src/converse-chatview.js index f62402c93..c05dc24ec 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -573,7 +573,7 @@ msg_content.innerHTML = u.addEmoji( _converse, emojione, u.addHyperlinks(xss.filterXSS(text, {'whiteList': {}})) ); - u.renderImageURLs(msg_content); + u.renderImageURLs(msg_content).then(this.scrollDown.bind(this)); return msg; }, diff --git a/src/utils.js b/src/utils.js index 703412530..6773f88b6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -180,15 +180,29 @@ }; u.renderImageURLs = function (obj) { + /* Returns a Promise which resolves once all images have been loaded. + */ const list = obj.textContent.match(URL_REGEX) || []; - _.forEach(list, function (url) { - isImage(url).then(function (img) { - img.className = 'chat-image'; - var anchors = sizzle(`a[href="${url}"]`, obj); - _.each(anchors, (a) => { a.innerHTML = img.outerHTML; }); - }); - }); - return obj; + return Promise.all( + _.map(list, (url) => + new Promise((resolve, reject) => + isImage(url).then(function (img) { + // XXX: need to create a new image, otherwise the event + // listener doesn't fire + const i = new Image(); + i.className = 'chat-image'; + i.src = img.src; + i.addEventListener('load', resolve); + // We also resolve for non-images, otherwise the + // Promise.all resolves prematurely. + i.addEventListener('error', resolve); + var anchors = sizzle(`a[href="${url}"]`, obj); + _.each(anchors, (a) => { + a.replaceChild(i, a.firstChild); + }); + }).catch(resolve) + ) + )) }; u.slideInAllElements = function (elements, duration=300) {