MDL-54687 core_message: added ajax scrolling for contacts

This commit is contained in:
Mark Nelson
2016-10-07 16:26:40 +08:00
parent 2a4bbaa3ff
commit 9661810ea6
11 changed files with 337 additions and 107 deletions
+2
View File
@@ -46,10 +46,12 @@ define(['jquery', 'core_message/message_area_actions', 'core_message/message_are
DELETEMESSAGES: "[data-action='delete-messages']",
DELETEMESSAGECHECKBOX: "[data-region='delete-message-checkbox']",
LASTMESSAGE: '.lastmessage',
LOADINGICON: '.loading-icon',
MESSAGE: "[data-region='message']",
MESSAGES: "[data-region='messages']",
MESSAGESAREA: "[data-region='messages-area']",
MESSAGERESPONSE: "[data-region='response']",
MESSAGETEXT: "[data-region='message-text']",
PROFILE: "[data-region='profile']",
PROFILEADDCONTACT: "[data-action='profile-add-contact']",
PROFILEBLOCKCONTACT: "[data-action='profile-block-contact']",
+4 -1
View File
@@ -39,7 +39,10 @@ define([], function() {
* Handles when we have selected to delete messages.
*/
Actions.prototype.chooseMessagesToDelete = function() {
this.messageArea.trigger(this.messageArea.EVENTS.CHOOSEMESSAGESTODELETE);
// Only fire the event if we are viewing messages.
if (this.messageArea.find(this.messageArea.SELECTORS.MESSAGES).length !== 0) {
this.messageArea.trigger(this.messageArea.EVENTS.CHOOSEMESSAGESTODELETE);
}
};
return Actions;
+249 -71
View File
@@ -21,8 +21,8 @@
* @copyright 2016 Mark Nelson <[email protected]>
* @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) {
/**
* Contacts class.
@@ -34,6 +34,30 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
this._init();
}
/** @type {Boolean} checks if we are currently deleting */
Contacts.prototype._isDeleting = false;
/** @type {Boolean} checks if we are currently loading conversations */
Contacts.prototype._isLoadingConversations = false;
/** @type {Boolean} checks if we are currently loading contacts */
Contacts.prototype._isLoadingContacts = false;
/** @type {int} the number of contacts displayed */
Contacts.prototype._numContactsDisplayed = 0;
/** @type {int} the number of contacts to retrieve */
Contacts.prototype._numContactsToRetrieve = 20;
/** @type {int} the number of conversations displayed */
Contacts.prototype._numConversationsDisplayed = 0;
/** @type {int} the number of conversations to retrieve */
Contacts.prototype._numConversationsToRetrieve = 20;
/** @type {int} the number of chars of the message to show */
Contacts.prototype._messageLength = 60;
/** @type {Messagearea} The messaging area object. */
Contacts.prototype.messageArea = null;
@@ -46,10 +70,13 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONSSELECTED, this._viewConversations.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTSSELECTED, this._viewContacts.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESDELETED, this._deleteConversations.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.SENDMESSAGE, this._viewConversationsWithUserSelected.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESENT, this._viewConversationsWithUserSelected.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTREMOVED, this._removeContact.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTADDED, this._viewContacts.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESENT, this._handleMessageSent.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTREMOVED, function(e, userid) {
this._removeContact(this.messageArea.SELECTORS.CONTACTS, userid);
}.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTADDED, function(e, userid) {
this._addContact(userid);
}.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CHOOSEMESSAGESTODELETE,
this._chooseConversationsToDelete.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CANCELDELETEMESSAGES,
@@ -57,52 +84,174 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.VIEWCONVERSATION,
this._viewConversation.bind(this));
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.VIEWPROFILE, this._viewContact.bind(this));
// Now enable the ability to infinitely scroll through conversations and contacts.
customEvents.define(this.messageArea.SELECTORS.CONVERSATIONS, [
customEvents.events.scrollBottom
]);
customEvents.define(this.messageArea.SELECTORS.CONTACTS, [
customEvents.events.scrollBottom
]);
this.messageArea.onDelegateEvent(customEvents.events.scrollBottom, this.messageArea.SELECTORS.CONVERSATIONS,
this._loadConversations.bind(this));
this.messageArea.onDelegateEvent(customEvents.events.scrollBottom, this.messageArea.SELECTORS.CONTACTS,
this._loadContacts.bind(this));
// Set the number of conversations that have been loaded on page load.
this._numConversationsDisplayed = this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS + " " +
this.messageArea.SELECTORS.CONTACT).length;
};
/**
* Handles viewing the list of conversations.
*
* @returns {Promise} The promise resolved when the contact area has been rendered,
* @private
*/
Contacts.prototype._viewConversations = function() {
if (this._isCurrentlyDeleting()) {
return;
}
return this._loadContactArea('core_message_data_for_messagearea_conversations');
};
/**
* Handles viewing the list of conversations and selecting a user.
*
* @param {Event} event The message sent event
* @param {int} userid The id of the user who the message was sent to
* @returns {Promise} The promise resolved when the message sent after actions are done
* @private
*/
Contacts.prototype._viewConversationsWithUserSelected = function(event, userid) {
if (this._isCurrentlyDeleting()) {
return;
}
return this._viewConversations().then(function() {
this._setSelectedUser(userid);
}.bind(this));
this.messageArea.find(this.messageArea.SELECTORS.CONTACTS).hide();
this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS).show();
};
/**
* Handles viewing the list of contacts.
*
* @returns {Promise} The promise resolved when the contact area has been rendered
* @private
*/
Contacts.prototype._viewContacts = function() {
if (this._isCurrentlyDeleting()) {
// If contacts is empty then load some.
if (this._numContactsDisplayed === 0) {
this._loadContacts();
}
this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS).hide();
this.messageArea.find(this.messageArea.SELECTORS.CONTACTS).show();
};
/**
* Handles when a message is sent.
*
* @param {Event} event The message sent event
* @param {int} userid The id of the user who the message was sent to
* @param {String} text The message text
* @private
*/
Contacts.prototype._handleMessageSent = function(event, userid, text) {
// Switch to viewing the conversations.
this._viewConversations();
// Get the text we will display on the contact panel.
text = this._getContactText(text);
// Get the user node.
var user = this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS + " " +
this.messageArea.SELECTORS.CONTACT + "[data-userid='" + userid + "']");
// If the user has not been loaded yet, let's copy the element from contact panel to the conversation panel.
if (user.length === 0) {
// Let's clone the data on the contact page.
var usercontact = this.messageArea.find(this.messageArea.SELECTORS.CONTACTS + " " +
this.messageArea.SELECTORS.CONTACT + "[data-userid='" + userid + "']");
user = usercontact.clone();
// Change the data action attribute.
user.attr('data-action', 'view-contact-msg');
// Increment the number of conversations displayed.
this._numConversationsDisplayed++;
}
// Move the contact to the top of the list.
user.prependTo(this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS));
// Scroll to the top.
this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS).scrollTop(0);
// Replace the text.
user.find(this.messageArea.SELECTORS.LASTMESSAGE).empty().append(text);
// Ensure user is selected.
this._setSelectedUser(userid);
};
/**
* Handles loading conversations.
*
* @returns {Promise} The promise resolved when the contact area has been rendered,
* @private
*/
Contacts.prototype._loadConversations = function() {
if (this._isDeleting) {
return;
}
return this._loadContactArea('core_message_data_for_messagearea_contacts');
if (this._isLoadingConversations) {
return;
}
// Tell the user we are loading items.
this._isLoadingConversations = true;
// Keep track of the number of contacts
var numberreceived = 0;
// Add loading icon to the end of the list.
return templates.render('core/loading', {}).then(function(html, js) {
templates.appendNodeContents(this.messageArea.SELECTORS.CONVERSATIONS,
"<div style='text-align:center'>" + html + "</div>", js);
return this._getItems('core_message_data_for_messagearea_conversations',
this._numConversationsDisplayed, this._numConversationsToRetrieve);
}.bind(this)).then(function(data) {
numberreceived = data.contacts.length;
return templates.render('core_message/message_area_contacts', data);
}).then(function(html, js) {
// Remove the loading icon.
this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS + " " +
this.messageArea.SELECTORS.LOADINGICON).remove();
// Only append data if we got data back.
if (numberreceived > 0) {
// Show the new content.
templates.appendNodeContents(this.messageArea.SELECTORS.CONVERSATIONS, html, js);
// Increment the number of conversations displayed.
this._numConversationsDisplayed += numberreceived;
}
// Mark that we are no longer busy loading data.
this._isLoadingConversations = false;
}.bind(this)).fail(notification.exception);
};
/**
* Handles loading contacts.
*
* @returns {Promise} The promise resolved when the contact area has been rendered
* @private
*/
Contacts.prototype._loadContacts = function() {
if (this._isDeleting) {
return;
}
if (this._isLoadingContacts) {
return;
}
// Tell the user we are loading items.
this._isLoadingContacts = true;
// Keep track of the number of contacts
var numberreceived = 0;
// Add loading icon to the end of the list.
return templates.render('core/loading', {}).then(function(html, js) {
templates.appendNodeContents(this.messageArea.SELECTORS.CONTACTS,
"<div style='text-align:center'>" + html + "</div>", js);
return this._getItems('core_message_data_for_messagearea_contacts',
this._numContactsDisplayed, this._numContactsToRetrieve);
}.bind(this)).then(function(data) {
numberreceived = data.contacts.length;
return templates.render('core_message/message_area_contacts', data);
}).then(function(html, js) {
// Remove the loading icon.
this.messageArea.find(this.messageArea.SELECTORS.CONTACTS + " " +
this.messageArea.SELECTORS.LOADINGICON).remove();
// Only append data if we got data back.
if (numberreceived > 0) {
// Show the new content.
templates.appendNodeContents(this.messageArea.SELECTORS.CONTACTS, html, js);
// Increment the number of contacts displayed.
this._numContactsDisplayed += numberreceived;
}
// Mark that we are no longer busy loading data.
this._isLoadingContacts = false;
}.bind(this)).fail(notification.exception);
};
/**
@@ -112,13 +261,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
* @private
*/
Contacts.prototype._viewConversation = function(event) {
if (this._isCurrentlyDeleting()) {
return;
if (!this._isDeleting) {
var userid = $(event.currentTarget).data('userid');
this._setSelectedUser(userid);
this.messageArea.trigger(this.messageArea.EVENTS.CONVERSATIONSELECTED, userid);
}
var userid = $(event.currentTarget).data('userid');
this._setSelectedUser(userid);
this.messageArea.trigger(this.messageArea.EVENTS.CONVERSATIONSELECTED, userid);
};
/**
@@ -128,7 +275,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
* @private
*/
Contacts.prototype._viewContact = function(event) {
if (!this._isCurrentlyDeleting()) {
if (!this._isDeleting) {
var userid = $(event.currentTarget).data('userid');
this._setSelectedUser(userid);
this.messageArea.trigger(this.messageArea.EVENTS.CONTACTSELECTED, userid);
@@ -136,33 +283,27 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
};
/**
* Handles loading the contact area.
* Handles returning a list of items to display.
*
* @param {String} webservice The web service to call
* @param {int} limitfrom
* @param {int} limitnum
* @returns {Promise} The promise resolved when the contact area has been rendered
* @private
*/
Contacts.prototype._loadContactArea = function(webservice) {
// Show loading template.
templates.render('core/loading', {}).done(function(html, js) {
templates.replaceNodeContents("[data-region='contacts']", html, js);
});
Contacts.prototype._getItems = function(webservice, limitfrom, limitnum) {
// Call the web service to return the data we want to view.
var promises = ajax.call([{
methodname: webservice,
args: {
userid: this.messageArea.getCurrentUserId()
userid: this.messageArea.getCurrentUserId(),
limitfrom: limitfrom,
limitnum: limitnum
}
}]);
// After the request render the contacts area.
return promises[0].then(function(data) {
// We have the data - lets re-render the template with it.
return templates.render('core_message/message_area_contacts', data);
}).then(function(html, js) {
templates.replaceNodeContents("[data-region='contacts-area']", html, js);
}).fail(notification.exception);
return promises[0];
};
/**
@@ -171,10 +312,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
* @private
*/
Contacts.prototype._chooseConversationsToDelete = function() {
// Only show the checkboxes for the contact if we are also deleting messages.
if (this.messageArea.find(this.messageArea.SELECTORS.DELETEMESSAGECHECKBOX).length !== 0) {
this.messageArea.find(this.messageArea.SELECTORS.DELETECONVERSATIONCHECKBOX).show();
}
this._isDeleting = true;
this.messageArea.find(this.messageArea.SELECTORS.DELETECONVERSATIONCHECKBOX).show();
};
/**
@@ -183,6 +322,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
* @private
*/
Contacts.prototype._cancelConversationsToDelete = function() {
this._isDeleting = false;
// Uncheck all checkboxes.
this.messageArea.find(this.messageArea.SELECTORS.DELETECONVERSATIONCHECKBOX + " input:checked").removeAttr('checked');
// Hide the checkboxes.
@@ -216,30 +356,67 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
if (requests.length > 0) {
ajax.call(requests)[requests.length - 1].then(function() {
for (var i = 0; i <= requests.length - 1; i++) {
// Remove the conversation.
this._removeContact(this.messageArea.SELECTORS.CONVERSATIONS, requests[i].args.otheruserid);
// Trigger conversation deleted events.
this.messageArea.trigger(this.messageArea.EVENTS.CONVERSATIONDELETED, requests[i].args.otheruserid);
}
}.bind(this), notification.exception);
}
// Check if the last message needs updating.
var user = this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS + " " +
this.messageArea.SELECTORS.CONTACT + "[data-userid='" + userid + "']");
if (user.length !== 0) {
var lastmessagelisted = user.find(this.messageArea.SELECTORS.LASTMESSAGE);
lastmessagelisted = lastmessagelisted.html();
// Go through and get the actual last message after all the deletions.
var messages = this.messageArea.find(this.messageArea.SELECTORS.MESSAGESAREA + " " +
this.messageArea.SELECTORS.MESSAGE);
var messageslength = messages.length;
messages.each(function(index, element) {
if (index === messageslength - 1) {
var actuallastmessage = $(element).find(this.messageArea.SELECTORS.MESSAGETEXT).html().trim();
if (lastmessagelisted != actuallastmessage) {
user.find(this.messageArea.SELECTORS.LASTMESSAGE).empty().append(
this._getContactText(actuallastmessage));
}
}
}.bind(this));
}
// Now we have done all the deletion we can set the flag back to false.
this._isDeleting = false;
// Hide all the checkboxes.
this._cancelConversationsToDelete();
};
// Reload conversation panel. We do this regardless if a conversation was deleted or not
// as a message may have been removed which means a conversation in the list may have to
// be moved.
this._viewConversationsWithUserSelected(event, userid);
/**
* Handles adding a contact to the list.
*
* @param {int} userid
* @private
*/
Contacts.prototype._addContact = function(userid) {
var user = this.messageArea.find(this.messageArea.SELECTORS.CONTACTS + " " + this.messageArea.SELECTORS.CONTACT +
"[data-userid='" + userid + "']").hide();
if (user.length !== 0) {
user.show();
}
};
/**
* Handles removing a contact from the list.
*
* @param {Event} event
* @param {String} selector
* @param {int} userid
* @private
*/
Contacts.prototype._removeContact = function(event, userid) {
this.messageArea.find(this.messageArea.SELECTORS.CONTACT + "[data-userid='" + userid + "']").remove();
Contacts.prototype._removeContact = function(selector, userid) {
this.messageArea.find(selector + " " + this.messageArea.SELECTORS.CONTACT +
"[data-userid='" + userid + "']").hide();
};
/**
@@ -256,16 +433,17 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
};
/**
* Checks if we are currently choosing conversations to delete.
* Converts a text message into the text that should be stored in the contact list
*
* @return {Boolean}
* @param {String} text
*/
Contacts.prototype._isCurrentlyDeleting = function() {
if (this.messageArea.find(this.messageArea.SELECTORS.DELETECONVERSATIONCHECKBOX + ":visible").length !== 0) {
return true;
Contacts.prototype._getContactText = function(text) {
if (text.length > this._messageLength) {
text = text.substr(0, this._messageLength - 3);
text += '...';
}
return false;
return text;
};
return Contacts;
+10 -7
View File
@@ -92,6 +92,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
* @private
*/
Messages.prototype._sendMessage = function() {
var text = this.messageArea.find(this.messageArea.SELECTORS.SENDMESSAGETEXT).val();
// Call the web service to save our message.
var promises = ajax.call([{
methodname: 'core_message_send_instant_messages',
@@ -99,7 +100,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
messages: [
{
touserid: this._getUserId(),
text: this.messageArea.find(this.messageArea.SELECTORS.SENDMESSAGETEXT).val()
text: text
}
]
}
@@ -107,10 +108,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
// Update the DOM when we get some data back.
return promises[0].then(function() {
// Some variables to pass to the trigger.
var userid = this._getUserId();
// Fire an event to say the message was sent.
this.messageArea.trigger(this.messageArea.EVENTS.MESSAGESENT, userid);
this.messageArea.trigger(this.messageArea.EVENTS.MESSAGESENT, [this._getUserId(), text]);
// Update the messaging area.
this._addMessageToDom();
}.bind(this)).fail(notification.exception);
@@ -179,15 +178,19 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification'],
"[data-blocktime='" + blocktime + "']").remove();
}
}.bind(this));
// Trigger event letting other modules know messages were deleted.
this.messageArea.trigger(this.messageArea.EVENTS.MESSAGESDELETED, this._getUserId());
}.bind(this), notification.exception);
} else {
// Trigger event letting other modules know messages were deleted.
this.messageArea.trigger(this.messageArea.EVENTS.MESSAGESDELETED, this._getUserId());
}
// Hide the items responsible for deleting messages.
this._hideDeleteAction();
// Trigger event letting other modules know messages were deleted.
this.messageArea.trigger(this.messageArea.EVENTS.MESSAGESDELETED,
this.messageArea.find(this.messageArea.SELECTORS.MESSAGES).data('userid'));
};
/**
+37
View File
@@ -33,6 +33,9 @@ define([], function() {
this._init();
}
/** @type {Boolean} checks if we are currently deleting */
Tabs.prototype._isDeleting = false;
/** @type {Messagearea} The messaging area object. */
Tabs.prototype.messageArea = null;
@@ -44,6 +47,18 @@ define([], function() {
Tabs.prototype._init = function() {
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.VIEWCONVERSATIONS, this._viewConversations.bind(this));
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.VIEWCONTACTS, this._viewContacts.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CHOOSEMESSAGESTODELETE, function() {
this._isDeleting = true;
}.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESDELETED, function() {
this._isDeleting = false;
}.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CANCELDELETEMESSAGES, function() {
this._isDeleting = false;
}.bind(this));
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESENT, function() {
this._selectTab(this.messageArea.SELECTORS.VIEWCONVERSATIONS, this.messageArea.SELECTORS.VIEWCONTACTS);
}.bind(this));
};
/**
@@ -52,7 +67,12 @@ define([], function() {
* @private
*/
Tabs.prototype._viewConversations = function() {
if (this._isDeleting) {
return;
}
this.messageArea.trigger(this.messageArea.EVENTS.CONVERSATIONSSELECTED);
this._selectTab(this.messageArea.SELECTORS.VIEWCONVERSATIONS, this.messageArea.SELECTORS.VIEWCONTACTS);
};
/**
@@ -61,7 +81,24 @@ define([], function() {
* @private
*/
Tabs.prototype._viewContacts = function() {
if (this._isDeleting) {
return;
}
this.messageArea.trigger(this.messageArea.EVENTS.CONTACTSSELECTED);
this._selectTab(this.messageArea.SELECTORS.VIEWCONTACTS, this.messageArea.SELECTORS.VIEWCONVERSATIONS);
};
/**
* Sets a tab to selected.
*
* @param {String} tabselect The name of the tab to select
* @param {String} tabdeselect The name of the tab to deselect
* @private
*/
Tabs.prototype._selectTab = function(tabselect, tabdeselect) {
this.messageArea.find(tabdeselect).removeClass('selected');
this.messageArea.find(tabselect).addClass('selected');
};
return Tabs;
+2 -2
View File
@@ -244,10 +244,10 @@ $settings->make_active();
// Get the renderer and the information we are going to be use.
$renderer = $PAGE->get_renderer('core_message');
if (!$user2realuser) {
$conversations = \core_message\api::get_conversations($user1->id);
$conversations = \core_message\api::get_conversations($user1->id, 0, 0, 20);
$messages = null;
} else {
$conversations = \core_message\api::get_conversations($user1->id, $user2->id);
$conversations = \core_message\api::get_conversations($user1->id, $user2->id, 0, 20);
$messages = \core_message\api::get_messages($user1->id, $user2->id);
}
$messagearea = new \core_message\output\message_area_page($user1->id, $conversations, $messages);
+1 -1
View File
@@ -17,7 +17,7 @@
<div class="row-fluid">
<div class="span3 contacts-area" data-region="contacts-area">
{{#contacts}}
{{> core_message/message_area_contacts }}
{{> core_message/message_area_contacts_area }}
{{/contacts}}
</div>
<div class="span9 messages-area" data-region="messages-area">
@@ -7,8 +7,10 @@
</div>
<div class="span8 information">
<div class="name">{{fullname}} {{#isonline}}*{{/isonline}}</div>
{{#lastmessage}}
<p class="lastmessage">{{.}}</p>
{{/lastmessage}}
<p class="lastmessage" data-region="lastmessage">
{{#lastmessage}}
{{.}}
{{/lastmessage}}
</p>
</div>
</div>
@@ -1,21 +1,3 @@
<div class="searcharea">
<form>
<label class="accesshide" for="filter{{uniqid}}">{{#str}}search{{/str}}</label>
<input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search{{/str}}" value="{{search}}">
</form>
</div>
<div class="contacts" data-region="contacts">
{{#contacts}}
{{> core_message/message_area_contact }}
{{/contacts}}
</div>
<div class="row-fluid tabs">
<div class="span6 tab tabconversations {{#conversationsselected}}selected{{/conversationsselected}}" data-action="conversations-view">
<div>{{#pix}}t/message, moodle{{/pix}}</div>
<div>{{#str}}conversations, message{{/str}}</div>
</div>
<div class="span6 tab tabcontacts {{^conversationsselected}}selected{{/conversationsselected}}" data-action="contacts-view">
<div>{{#pix}}i/cohort, moodle{{/pix}}</div>
<div>{{#str}}contacts, message{{/str}}</div>
</div>
</div>
{{#contacts}}
{{> core_message/message_area_contact }}
{{/contacts}}
@@ -0,0 +1,21 @@
<div class="searcharea">
<form>
<label class="accesshide" for="filter{{uniqid}}">{{#str}}search{{/str}}</label>
<input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search{{/str}}" value="{{search}}">
</form>
</div>
<div class="contacts" data-region="contacts" data-region-content="{{#conversationsselected}}conversations{{/conversationsselected}}{{^conversationsselected}}contacts{{/conversationsselected}}">
{{> core_message/message_area_contacts }}
</div>
{{! Hidden div to load the other tabs items in via JS when appropriate. }}
<div class="contacts" data-region="contacts" data-region-content="{{#conversationsselected}}contacts{{/conversationsselected}}{{^conversationsselected}}conversations{{/conversationsselected}}" style="display:none;"></div>
<div class="row-fluid tabs">
<div class="span6 tab tabconversations {{#conversationsselected}}selected{{/conversationsselected}}" data-action="conversations-view">
<div>{{#pix}}t/message, moodle{{/pix}}</div>
<div>{{#str}}conversations, message{{/str}}</div>
</div>
<div class="span6 tab tabcontacts {{^conversationsselected}}selected{{/conversationsselected}}" data-action="contacts-view">
<div>{{#pix}}i/cohort, moodle{{/pix}}</div>
<div>{{#str}}contacts, message{{/str}}</div>
</div>
</div>
@@ -8,7 +8,9 @@
<input type="checkbox" data-messageid="{{id}}" data-messageread="{{isread}}"/>
</div>
<div class="span11 content {{position}}">
{{{text}}}
<span data-region="message-text">
{{{text}}}
</span>
<span class="timesent">
{{timesent}}
</span>