mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-54687 core_message: added ajax scrolling for messages
This commit is contained in:
parent
90525930e5
commit
8ec78c48fa
@ -21,8 +21,8 @@
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
function($, ajax, templates, notification) {
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/custom_interaction_events'],
|
||||
function($, ajax, templates, notification, customEvents) {
|
||||
|
||||
/**
|
||||
* Messages class.
|
||||
@ -34,6 +34,15 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Boolean} checks if we are currently loading messages */
|
||||
Messages.prototype._isLoadingMessages = false;
|
||||
|
||||
/** @type {int} the number of messagess displayed */
|
||||
Messages.prototype._numMessagesDisplayed = 0;
|
||||
|
||||
/** @type {int} the number of messages to retrieve */
|
||||
Messages.prototype._numMessagesToRetrieve = 20;
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Messages.prototype.messageArea = null;
|
||||
|
||||
@ -44,8 +53,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
*/
|
||||
Messages.prototype._init = function() {
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONDELETED, this._handleConversationDeleted.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONSELECTED, this._loadMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.SENDMESSAGE, this._loadMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONSELECTED, this._viewMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.SENDMESSAGE, this._viewMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CHOOSEMESSAGESTODELETE, this._chooseMessagesToDelete.bind(this));
|
||||
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.SENDMESSAGE, this._sendMessage.bind(this));
|
||||
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.DELETEMESSAGES, this._deleteMessages.bind(this));
|
||||
@ -54,35 +63,121 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads messages for a specific user.
|
||||
* View the message panel.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {int} userid
|
||||
* @returns {Promise} The promise resolved when the messages have been loaded.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._loadMessages = function(event, userid) {
|
||||
// Show loading template.
|
||||
templates.render('core/loading', {}).done(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.MESSAGESAREA, html, js);
|
||||
}.bind(this));
|
||||
Messages.prototype._viewMessages = function(event, userid) {
|
||||
// We are viewing another user, or re-loading the panel, so set number of messages displayed to 0.
|
||||
this._numMessagesDisplayed = 0;
|
||||
|
||||
// Keep track of the number of messages received.
|
||||
var numberreceived = 0;
|
||||
// Show loading template.
|
||||
return templates.render('core/loading', {}).then(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.MESSAGESAREA, html, js);
|
||||
return this._getMessages(userid);
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.messages.length;
|
||||
// We have the data - lets render the template with it.
|
||||
return templates.render('core_message/message_area_messages_area', data);
|
||||
}).then(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.MESSAGESAREA, html, js);
|
||||
// Scroll to the bottom.
|
||||
this._scrollBottom();
|
||||
// Only increment if data was returned.
|
||||
if (numberreceived > 0) {
|
||||
// Set the number of messages displayed.
|
||||
this._numMessagesDisplayed = numberreceived;
|
||||
}
|
||||
// Now enable the ability to infinitely scroll through messages.
|
||||
customEvents.define(this.messageArea.SELECTORS.MESSAGES, [
|
||||
customEvents.events.scrollTop
|
||||
]);
|
||||
// Assign the event for scrolling.
|
||||
this.messageArea.onCustomEvent(customEvents.events.scrollTop, this._loadMessages.bind(this));
|
||||
}.bind(this)).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads messages while scrolling.
|
||||
*
|
||||
* @returns {Promise} The promise resolved when the messages have been loaded.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._loadMessages = function() {
|
||||
if (this._isLoadingMessages) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isLoadingMessages = true;
|
||||
|
||||
// Keep track of the number of messages received.
|
||||
var numberreceived = 0;
|
||||
// Show loading template.
|
||||
return templates.render('core/loading', {}).then(function(html, js) {
|
||||
templates.prependNodeContents(this.messageArea.SELECTORS.MESSAGES,
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return this._getMessages(this._getUserId());
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.messages.length;
|
||||
// We have the data - lets render the template with it.
|
||||
return templates.render('core_message/message_area_messages', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.MESSAGES + " " +
|
||||
this.messageArea.SELECTORS.LOADINGICON).remove();
|
||||
// Check if we got something to do.
|
||||
if (numberreceived > 0) {
|
||||
// Let's check if we can remove the block time.
|
||||
// First, get the block time that is currently being displayed.
|
||||
var blocktime = this.messageArea.node.find(this.messageArea.SELECTORS.BLOCKTIME + ":first");
|
||||
var newblocktime = $(html).find(this.messageArea.SELECTORS.BLOCKTIME + ":first").addBack();
|
||||
if (blocktime.html() == newblocktime.html()) {
|
||||
// Remove the block time as it's present above.
|
||||
blocktime.remove();
|
||||
}
|
||||
// Get height before we add the messages.
|
||||
var oldheight = this.messageArea.find(this.messageArea.SELECTORS.MESSAGES)[0].scrollHeight;
|
||||
// Show the new content.
|
||||
templates.prependNodeContents(this.messageArea.SELECTORS.MESSAGES, html, js);
|
||||
// Get height after we add the messages.
|
||||
var newheight = this.messageArea.find(this.messageArea.SELECTORS.MESSAGES)[0].scrollHeight;
|
||||
// Make sure scroll bar is at the location before we loaded more messages.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.MESSAGES).scrollTop(newheight - oldheight);
|
||||
// Increment the number of messages displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoadingMessages = false;
|
||||
}.bind(this)).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles returning a list of messages to display.
|
||||
*
|
||||
* @param {int} userid
|
||||
* @returns {Promise} The promise resolved when the contact area has been rendered
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._getMessages = function(userid) {
|
||||
// Call the web service to get our data.
|
||||
var promises = ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_messages',
|
||||
args: {
|
||||
currentuserid: this.messageArea.getCurrentUserId(),
|
||||
otheruserid: userid
|
||||
otheruserid: userid,
|
||||
limitfrom: this._numMessagesDisplayed,
|
||||
limitnum: this._numMessagesToRetrieve,
|
||||
newest: true
|
||||
}
|
||||
}]);
|
||||
|
||||
// Do stuff when we get data back.
|
||||
return promises[0].then(function(data) {
|
||||
// We have the data - lets re-render the template with it.
|
||||
return templates.render('core_message/message_area_messages', data);
|
||||
}).then(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.MESSAGESAREA, html, js);
|
||||
}.bind(this)).fail(notification.exception);
|
||||
return promises[0];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -264,6 +359,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
templates.appendNodeContents(this.messageArea.SELECTORS.MESSAGES, html, js);
|
||||
// Empty the response text area.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SENDMESSAGETEXT).val('');
|
||||
// Scroll down.
|
||||
this._scrollBottom();
|
||||
}.bind(this)).fail(notification.exception);
|
||||
};
|
||||
|
||||
@ -277,6 +374,17 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
|
||||
return this.messageArea.find(this.messageArea.SELECTORS.MESSAGES).data('userid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Scrolls to the bottom of the messages.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._scrollBottom = function() {
|
||||
// Scroll to the bottom.
|
||||
var messages = this.messageArea.find(this.messageArea.SELECTORS.MESSAGES);
|
||||
messages.scrollTop(messages[0].scrollHeight);
|
||||
};
|
||||
|
||||
return Messages;
|
||||
}
|
||||
);
|
@ -91,11 +91,12 @@ class api {
|
||||
* @param int $otheruserid the other user
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @param string $sort
|
||||
* @return \core_message\output\messages
|
||||
*/
|
||||
public static function get_messages($userid, $otheruserid, $limitfrom = 0, $limitnum = 0) {
|
||||
public static function get_messages($userid, $otheruserid, $limitfrom = 0, $limitnum = 0, $sort = 'timecreated ASC') {
|
||||
$arrmessages = array();
|
||||
if ($messages = \core_message\helper::get_messages($userid, $otheruserid, 0, $limitfrom, $limitnum)) {
|
||||
if ($messages = \core_message\helper::get_messages($userid, $otheruserid, 0, $limitfrom, $limitnum, $sort)) {
|
||||
$arrmessages = \core_message\helper::create_messages($userid, $messages);
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,13 @@ class helper {
|
||||
// Store the messages.
|
||||
$arrmessages = array();
|
||||
|
||||
// We always view messages from oldest to newest, ensure we have it in that order.
|
||||
$lastmessage = end($messages);
|
||||
$firstmessage = reset($messages);
|
||||
if ($lastmessage->timecreated < $firstmessage->timecreated) {
|
||||
$messages = array_reverse($messages);
|
||||
}
|
||||
|
||||
// Keeps track of the last day, month and year combo we were viewing.
|
||||
$day = '';
|
||||
$month = '';
|
||||
|
@ -554,7 +554,8 @@ class core_message_external extends external_api {
|
||||
'currentuserid' => new external_value(PARAM_INT, 'The current user\'s id'),
|
||||
'otheruserid' => new external_value(PARAM_INT, 'The other user\'s id'),
|
||||
'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0),
|
||||
'newest' => new external_value(PARAM_BOOL, 'Newest first?', VALUE_DEFAULT, false),
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -566,9 +567,10 @@ class core_message_external extends external_api {
|
||||
* @param int $otheruserid The other user's id
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @param boolean $newest
|
||||
* @return external_description
|
||||
*/
|
||||
public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0) {
|
||||
public static function data_for_messagearea_messages($currentuserid, $otheruserid, $limitfrom = 0, $limitnum = 0, $newest = false) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Check if messaging is enabled.
|
||||
@ -580,13 +582,19 @@ class core_message_external extends external_api {
|
||||
'currentuserid' => $currentuserid,
|
||||
'otheruserid' => $otheruserid,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum
|
||||
'limitnum' => $limitnum,
|
||||
'newest' => $newest
|
||||
);
|
||||
self::validate_parameters(self::data_for_messagearea_messages_parameters(), $params);
|
||||
|
||||
self::validate_context(context_user::instance($currentuserid));
|
||||
|
||||
$messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom, $limitnum);
|
||||
if ($newest) {
|
||||
$sort = 'timecreated DESC';
|
||||
} else {
|
||||
$sort = 'timecreated ASC';
|
||||
}
|
||||
$messages = \core_message\api::get_messages($currentuserid, $otheruserid, $limitfrom, $limitnum, $sort);
|
||||
|
||||
$renderer = $PAGE->get_renderer('core_message');
|
||||
return $messages->export_for_template($renderer);
|
||||
|
@ -22,7 +22,7 @@
|
||||
</div>
|
||||
<div class="span9 messages-area" data-region="messages-area">
|
||||
{{#messages}}
|
||||
{{> core_message/message_area_messages }}
|
||||
{{> core_message/message_area_messages_area }}
|
||||
{{/messages}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,13 +1,3 @@
|
||||
<div class="messages" data-region="messages" data-userid="{{otheruserid}}">
|
||||
<div class="name">
|
||||
{{otheruserfullname}}
|
||||
</div>
|
||||
{{#messages}}
|
||||
{{> core_message/message_area_message }}
|
||||
{{/messages}}
|
||||
</div>
|
||||
<div class="response" data-region="response">
|
||||
{{#iscurrentuser}}
|
||||
{{> core_message/message_area_response }}
|
||||
{{/iscurrentuser}}
|
||||
</div>
|
||||
{{#messages}}
|
||||
{{> core_message/message_area_message }}
|
||||
{{/messages}}
|
11
message/templates/message_area_messages_area.mustache
Normal file
11
message/templates/message_area_messages_area.mustache
Normal file
@ -0,0 +1,11 @@
|
||||
<div class="name">
|
||||
{{otheruserfullname}}
|
||||
</div>
|
||||
<div class="messages" data-region="messages" data-userid="{{otheruserid}}">
|
||||
{{> core_message/message_area_messages }}
|
||||
</div>
|
||||
<div class="response" data-region="response">
|
||||
{{#iscurrentuser}}
|
||||
{{> core_message/message_area_response }}
|
||||
{{/iscurrentuser}}
|
||||
</div>
|
@ -156,13 +156,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.messages {
|
||||
height: 520px;
|
||||
overflow-y: auto;
|
||||
.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.messages {
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
|
||||
.blocktime {
|
||||
clear: both;
|
||||
|
@ -5879,13 +5879,13 @@ a.ygtvspacer:hover {
|
||||
.messaging-area .messages-area .profile .actions {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.messaging-area .messages-area .messages {
|
||||
height: 520px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.messaging-area .messages-area .messages .name {
|
||||
.messaging-area .messages-area .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.messaging-area .messages-area .messages {
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.messaging-area .messages-area .messages .blocktime {
|
||||
clear: both;
|
||||
font-weight: bold;
|
||||
|
Loading…
x
Reference in New Issue
Block a user