weekly release 2.8dev
[moodle.git] / mod / chat / gui_ajax / module.js
CommitLineData
2daed78a
PS
1/*
2 * NOTE: the /mod/chat/gui_header_js/ is not a real plugin,
3 * ideally this code should be in /mod/chat/module.js
4 */
5
6/**
7 * @namespace M.mod_chat_ajax
8 */
9M.mod_chat_ajax = M.mod_chat_ajax || {};
10
579a4976 11/**
2daed78a
PS
12 * Init ajax based Chat UI.
13 * @namespace M.mod_chat_ajax
14 * @function
15 * @param {YUI} Y
16 * @param {Object} cfg configuration data
579a4976 17 */
2daed78a
PS
18M.mod_chat_ajax.init = function(Y, cfg) {
19
20 var gui_ajax = {
579a4976 21
c52b4db5
AD
22 // Properties.
23 api : M.cfg.wwwroot + '/mod/chat/chat_ajax.php?sesskey=' + M.cfg.sesskey, // The path to the ajax callback script.
24 cfg : {}, // A configuration variable.
25 interval : null, // The interval object for refreshes.
26 layout : null, // A reference to the layout used in this module.
27 messages : [], // An array of messages.
28 scrollable : true, // True is scrolling should occur.
29 thememenu : null, // A reference to the menu for changing themes.
579a4976
SH
30
31 // Elements
32 messageinput : null,
33 sendbutton : null,
34 messagebox : null,
35
2daed78a 36 init : function(cfg) {
579a4976
SH
37 this.cfg = cfg;
38 this.cfg.req_count = this.cfg.req_count || 0;
e9c599cb
AD
39 participantswidth = 180;
40 if (Y.one('#input-message').get('docWidth') < 640) {
41 participantswidth = 120;
42 }
69ccc32d 43 this.layout = new Y.YUI2.widget.Layout({
579a4976 44 units : [
e9c599cb
AD
45 {position: 'right', width: participantswidth, resize: true, gutter: '1px', scroll: true, body: 'chat-userlist', animate: false},
46 {position: 'bottom', height: 42, resize: false, body: 'chat-input-area', gutter: '1px', collapse: false, resize: false},
47 {position: 'center', body: 'chat-messages', gutter: '0px', scroll: true}
579a4976
SH
48 ]
49 });
50
51 this.layout.on('render', function() {
7d2975c1
DC
52 var unit = this.getUnitByPosition('right');
53 if (unit) {
54 unit.on('close', function() {
55 closeLeft();
56 });
57 }
579a4976
SH
58 }, this.layout);
59 this.layout.render();
60
c52b4db5 61 // Gather the general elements.
579a4976
SH
62 this.messageinput = Y.one('#input-message');
63 this.sendbutton = Y.one('#button-send');
64 this.messagebox = Y.one('#chat-messages');
65
c52b4db5 66 // Set aria attributes to messagebox and chat-userlist.
02a011ea
RT
67 this.messagebox.set('role', 'log');
68 this.messagebox.set('aria-live', 'polite');
69 var userlist = Y.one('#chat-userlist');
70 userlist.set('aria-live', 'polite');
71 userlist.set('aria-relevant', 'all');
72
c52b4db5 73 // Attach the default events for this module.
579a4976 74 this.sendbutton.on('click', this.send, this);
2daed78a
PS
75 this.messagebox.on('mouseenter', function() {
76 this.scrollable = false;
77 }, this);
78 this.messagebox.on('mouseleave', function() {
79 this.scrollable = true;
80 }, this);
579a4976 81
c52b4db5 82 // Send the message when the enter key is pressed.
579a4976
SH
83 Y.on('key', this.send, this.messageinput, 'press:13', this);
84
85 document.title = this.cfg.chatroom_name;
86
c52b4db5 87 // Prepare and execute the first AJAX request of information.
579a4976
SH
88 Y.io(this.api,{
89 method : 'POST',
90 data : build_querystring({
91 action : 'init',
92 chat_init : 1,
93 chat_sid : this.cfg.sid,
94 theme : this.theme
95 }),
96 on : {
97 success : function(tid, outcome) {
5be94998 98 this.messageinput.removeAttribute('disabled');
579a4976 99 this.messageinput.set('value', '');
c67a139c 100 this.messageinput.focus();
579a4976
SH
101 try {
102 var data = Y.JSON.parse(outcome.responseText);
103 } catch (ex) {
104 return;
105 }
106 this.update_users(data.users);
107 }
108 },
109 context : this
110 });
111
c67a139c
DC
112 var scope = this;
113 this.interval = setInterval(function() {
114 scope.update_messages();
579a4976
SH
115 }, this.cfg.timer, this);
116
c52b4db5 117 // Create and initalise theme changing menu.
69ccc32d 118 this.thememenu = new Y.YUI2.widget.Menu('basicmenu', {xy:[0,0]});
579a4976 119 this.thememenu.addItems([
c52b4db5
AD
120 {text: M.util.get_string('bubble', 'mod_chat'), url: this.cfg.chaturl + '&theme=bubble'},
121 {text: M.util.get_string('compact', 'mod_chat'), url: this.cfg.chaturl + '&theme=compact'}
579a4976 122 ]);
b661e76c 123 if (this.cfg.showcoursetheme == 1) {
c52b4db5 124 this.thememenu.addItem({text: M.util.get_string('coursetheme', 'mod_chat'), url: this.cfg.chaturl + '&theme=course_theme'});
b661e76c 125 }
579a4976 126 this.thememenu.render(document.body);
c52b4db5
AD
127 Y.one('#choosetheme').on('click', function(e) {
128 this.moveTo((e.pageX - 20), (e.pageY - 20));
579a4976
SH
129 this.show();
130 }, this.thememenu);
131 },
132
133 append_message : function(key, message, row) {
c52b4db5
AD
134 var item = Y.Node.create('<li id="mdl-chat-entry-' + key + '">' + message.message + '</li>');
135 item.addClass((message.mymessage) ? 'mdl-chat-my-entry' : 'mdl-chat-entry');
579a4976
SH
136 Y.one('#messages-list').append(item);
137 if (message.type && message.type == 'beep') {
138 Y.one('#chat-notify').setContent('<embed src="../beep.wav" autostart="true" hidden="true" name="beep" />');
139 }
140 },
141
142 send : function(e, beep) {
b661e76c 143 this.sendbutton.set('value', M.str.chat.sending);
579a4976 144 var data = {
c52b4db5 145 chat_message : (!beep) ? this.messageinput.get('value') : '',
2daed78a
PS
146 chat_sid : this.cfg.sid,
147 theme : this.cfg.theme
148 };
149 if (beep) {
150 data.beep = beep
151 }
467902f2 152 data.action = 'chat';
579a4976 153
467902f2 154 Y.io(this.api, {
2daed78a
PS
155 method : 'POST',
156 data : build_querystring(data),
157 on : {
158 success : this.send_callback
159 },
160 context : this
579a4976
SH
161 });
162 },
163
164 send_callback : function(tid, outcome, args) {
529817c8
DC
165 try {
166 var data = Y.JSON.parse(outcome.responseText);
167 } catch (ex) {
168 return;
579a4976 169 }
529817c8
DC
170 this.sendbutton.set('value', M.str.chat.send);
171 this.messageinput.set('value', '');
579a4976
SH
172 clearInterval(this.interval);
173 this.update_messages();
58f3f058
DC
174 var scope = this;
175 this.interval = setInterval(function() {
176 scope.update_messages();
579a4976
SH
177 }, this.cfg.timer, this);
178 },
179
e8a4928d 180 talkto: function (e, name) {
c52b4db5 181 this.messageinput.set('value', "To " + name + ": ");
579a4976
SH
182 this.messageinput.focus();
183 },
184
185 update_messages : function() {
186 this.cfg.req_count++;
467902f2 187 Y.io(this.api, {
579a4976
SH
188 method : 'POST',
189 data : build_querystring({
467902f2 190 action: 'update',
579a4976
SH
191 chat_lastrow : this.cfg.chat_lastrow || false,
192 chat_lasttime : this.cfg.chat_lasttime,
193 chat_sid : this.cfg.sid,
194 theme : this.cfg.theme
195 }),
196 on : {
197 success : this.update_messages_callback
198 },
199 context : this
200 });
201 },
202
203 update_messages_callback : function(tid, outcome) {
204 try {
205 var data = Y.JSON.parse(outcome.responseText);
206 } catch (ex) {
207 return;
208 }
209 if (data.error) {
a8e3b008
DC
210 clearInterval(this.interval);
211 alert(data.error);
212 window.location = this.cfg.home;
579a4976
SH
213 }
214 this.cfg.chat_lasttime = data.lasttime;
215 this.cfg.chat_lastrow = data.lastrow;
c52b4db5 216 // Update messages.
579a4976 217 for (var key in data.msgs){
2daed78a 218 if (!M.util.in_array(key, this.messages)) {
579a4976
SH
219 this.messages.push(key);
220 this.append_message(key, data.msgs[key], data.lastrow);
221 }
222 }
c52b4db5 223 // Update users.
579a4976
SH
224 this.update_users(data.users);
225 // Scroll to the bottom of the message list
226 if (this.scrollable) {
c52b4db5 227 Y.Node.getDOMNode(this.messagebox).parentNode.scrollTop += 500;
579a4976
SH
228 }
229 this.messageinput.focus();
230 },
231
232 update_users : function(users) {
2daed78a 233 if (!users) {
579a4976
SH
234 return;
235 }
236 var list = Y.one('#users-list');
237 list.get('children').remove();
238 for (var i in users) {
c52b4db5 239 var li = Y.Node.create('<li><table><tr><td>' + users[i].picture + '</td><td></td></tr></table></li>');
579a4976 240 if (users[i].id == this.cfg.userid) {
c52b4db5 241 li.all('td').item(1).append(Y.Node.create('<strong><a target="_blank" href="' + users[i].url + '">' + users[i].name + '</a></strong>'));
579a4976 242 } else {
c52b4db5
AD
243 li.all('td').item(1).append(Y.Node.create('<div><a target="_blank" href="' + users[i].url + '">' + users[i].name + '</a></div>'));
244 var talk = Y.Node.create('<a href="###">' + M.str.chat.talk + '</a>');
e8a4928d 245 talk.on('click', this.talkto, this, users[i].name);
c52b4db5 246 var beep = Y.Node.create('<a href="###">' + M.str.chat.beep + '</a>');
e8a4928d 247 beep.on('click', this.send, this, users[i].id);
9d3b8b24 248 li.all('td').item(1).append(Y.Node.create('<div></div>').append(talk).append('&nbsp;').append(beep));
579a4976
SH
249 }
250 list.append(li);
251 }
252 }
2daed78a
PS
253
254 };
255
256 gui_ajax.init(cfg);
257};