weekly release 2.9dev
[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) {
b12c3878 143 if((this.messageinput.get('value') != '') || (typeof beep != 'undefined')) {
144 this.sendbutton.set('value', M.str.chat.sending);
145 var data = {
146 chat_message : (!beep) ? this.messageinput.get('value') : '',
147 chat_sid : this.cfg.sid,
148 theme : this.cfg.theme
149 };
150 if (beep) {
151 data.beep = beep
152 }
153 data.action = 'chat';
154
155 Y.io(this.api, {
156 method : 'POST',
157 data : build_querystring(data),
158 on : {
159 success : this.send_callback
160 },
161 context : this
162 });
2daed78a 163 }
579a4976
SH
164 },
165
166 send_callback : function(tid, outcome, args) {
529817c8
DC
167 try {
168 var data = Y.JSON.parse(outcome.responseText);
169 } catch (ex) {
170 return;
579a4976 171 }
529817c8
DC
172 this.sendbutton.set('value', M.str.chat.send);
173 this.messageinput.set('value', '');
579a4976
SH
174 clearInterval(this.interval);
175 this.update_messages();
58f3f058
DC
176 var scope = this;
177 this.interval = setInterval(function() {
178 scope.update_messages();
579a4976
SH
179 }, this.cfg.timer, this);
180 },
181
e8a4928d 182 talkto: function (e, name) {
c52b4db5 183 this.messageinput.set('value', "To " + name + ": ");
579a4976
SH
184 this.messageinput.focus();
185 },
186
187 update_messages : function() {
188 this.cfg.req_count++;
467902f2 189 Y.io(this.api, {
579a4976
SH
190 method : 'POST',
191 data : build_querystring({
467902f2 192 action: 'update',
579a4976
SH
193 chat_lastrow : this.cfg.chat_lastrow || false,
194 chat_lasttime : this.cfg.chat_lasttime,
195 chat_sid : this.cfg.sid,
196 theme : this.cfg.theme
197 }),
198 on : {
199 success : this.update_messages_callback
200 },
201 context : this
202 });
203 },
204
205 update_messages_callback : function(tid, outcome) {
206 try {
207 var data = Y.JSON.parse(outcome.responseText);
208 } catch (ex) {
209 return;
210 }
211 if (data.error) {
a8e3b008
DC
212 clearInterval(this.interval);
213 alert(data.error);
214 window.location = this.cfg.home;
579a4976
SH
215 }
216 this.cfg.chat_lasttime = data.lasttime;
217 this.cfg.chat_lastrow = data.lastrow;
c52b4db5 218 // Update messages.
579a4976 219 for (var key in data.msgs){
2daed78a 220 if (!M.util.in_array(key, this.messages)) {
579a4976
SH
221 this.messages.push(key);
222 this.append_message(key, data.msgs[key], data.lastrow);
223 }
224 }
c52b4db5 225 // Update users.
579a4976
SH
226 this.update_users(data.users);
227 // Scroll to the bottom of the message list
228 if (this.scrollable) {
c52b4db5 229 Y.Node.getDOMNode(this.messagebox).parentNode.scrollTop += 500;
579a4976
SH
230 }
231 this.messageinput.focus();
232 },
233
234 update_users : function(users) {
2daed78a 235 if (!users) {
579a4976
SH
236 return;
237 }
238 var list = Y.one('#users-list');
239 list.get('children').remove();
240 for (var i in users) {
c52b4db5 241 var li = Y.Node.create('<li><table><tr><td>' + users[i].picture + '</td><td></td></tr></table></li>');
579a4976 242 if (users[i].id == this.cfg.userid) {
c52b4db5 243 li.all('td').item(1).append(Y.Node.create('<strong><a target="_blank" href="' + users[i].url + '">' + users[i].name + '</a></strong>'));
579a4976 244 } else {
c52b4db5
AD
245 li.all('td').item(1).append(Y.Node.create('<div><a target="_blank" href="' + users[i].url + '">' + users[i].name + '</a></div>'));
246 var talk = Y.Node.create('<a href="###">' + M.str.chat.talk + '</a>');
e8a4928d 247 talk.on('click', this.talkto, this, users[i].name);
c52b4db5 248 var beep = Y.Node.create('<a href="###">' + M.str.chat.beep + '</a>');
e8a4928d 249 beep.on('click', this.send, this, users[i].id);
9d3b8b24 250 li.all('td').item(1).append(Y.Node.create('<div></div>').append(talk).append('&nbsp;').append(beep));
579a4976
SH
251 }
252 list.append(li);
253 }
254 }
2daed78a
PS
255
256 };
257
258 gui_ajax.init(cfg);
259};