Reputation: 11663
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;
}
};
Upvotes: 0
Views: 262
Reputation: 1952
In Javascript you can store functions in variables, this is what you did with onComplete()
.
The img object will execute a function(so called callback) after successfully loading the image (onload) or if it could not load the image(onerror).
To tell the img object which method to call after those events, you need to give it the method name like this without parenthesis:
img.onload = onComplete;
img.onerror = onComplete;
If you would use parenthesis the function would be executed immediately and img.onload
wouldn't contain a reference to a function but the result of onCompleted.
Upvotes: 1
Reputation: 65274
img.onload = onComplete;
will assign the function onComplete
to the onload
handler. THis means, that the function is called, when the vent happens.
img.onload = onComplete();
will assign the result of calling the function onComplete
to the onload
handler. This means, that the function is called immediately, is expected to return another function (or a string containing valid JS), which in turn will be called when the event happens.
Upvotes: 0
Reputation: 943579
The HTMLImageElement
object will cause functions assigned to its onload
and onerror
properties to be called at the appropriate times (i.e. when the HTTP response is received or the wait for it times out).
The code to do this is built into the browser. The properties (or the addEventListener
function in more modern code) are the only ways with which you can interact with that code.
Upvotes: 1