The following renderChat function is used to render a message and an image onto a chat board. Inside the function there is another function
var onComplete = function () {
which does all the work of creating the list element and appending it to the chat list. After the onComplete function, there is only this three lines of code
img.onload = onComplete;
img.onerror = onComplete;
img.src = c.chat.value.media;
Because the var onComplete is a function assigned to a variable, I assumed it had to be called with parenthesis. Thus, when I see this
img.onload = onComplete;
I understand that the function has been assigned to a new variable, but has never been called. Yet, when I use the application, the chat has been rendered by the time we reach img.src = c.chat.value.media;
Can you please explain how my understanding of JavaScript is mistaken and how this function is working?
var renderChat = function (c) {
debug("Rendering chat: key='%s' fingerprint='%s' message='%s' created='%s' imageMd5='%s'",
c.chat.key,
c.chat.value.fingerprint,
c.chat.value.message,
c.chat.value.created,
md5(c.chat.value.media));
var renderFP = c.chat.value.fingerprint;
if (!isMuted(renderFP)) {
var img = new Image();
var onComplete = function () {
// Don't want duplicates and don't want muted messages
if (body.find('li[data-key="' + c.chat.key + '"]').length === 0 &&
!isMuted(renderFP)) {
var li = document.createElement('li');
li.dataset.action = 'chat-message';
li.dataset.key = c.chat.key;
li.dataset.fingerprint = renderFP;
li.appendChild(img);
// This is likely your own fingerprint so you don't mute yourself. Unless you're weird.
if (userId.val() !== renderFP) {
updateNotificationCount();
var btn = document.createElement('button');
btn.textContent = 'mute';
btn.className = 'mute';
li.appendChild(btn);
}
var message = document.createElement('p');
message.textContent = c.chat.value.message;
message.innerHTML = transform(message.innerHTML);
li.appendChild(message);
var createdDate = moment(new Date(c.chat.value.created));
var timestamp = document.createElement('time');
timestamp.setAttribute('datetime', createdDate.toISOString());
timestamp.textContent = createdDate.format('LT');
timestamp.className = 'timestamp';
li.appendChild(timestamp);
var size = addChat.is(":visible") ? addChat[0].getBoundingClientRect().bottom : $(window).innerHeight();
var last = chatList[0].lastChild;
var bottom = last ? last.getBoundingClientRect().bottom : 0;
var follow = bottom < size + 50;
chatList.append(li);
setupWaypoints(li);
debug('Appended chat %s', c.chat.key);
// if scrolled to bottom of window then scroll the new thing into view
// otherwise, you are reading the history... allow user to scroll up.
if (follow) {
var children = chatList.children();
if (children.length > CHAT_LIMIT) {
children.first().remove().waypoint('destroy');
}
li.scrollIntoView();
}
}
};
img.onload = onComplete;
img.onerror = onComplete;
img.src = c.chat.value.media;
}
};
img.onload = onComplete;you assign a function object to theonloadevent. So the function executes at some point, when the image is loaded. If you execute the function right away, you assign the returned value of the function to the event, that expects a function to be called.