[IMP] Use JTabWidget for Instant Messaging dialog
[cds-indico.git] / indico / MaKaC / plugins / InstantMessaging / htdocs / js / InstantMessaging.js
blobc4c09a38d727a9b999151a1f34c2cd0471714ab8
2 /**
3  * Dictionary that maps booking ids to the state of the chatroom info text that can be shown or hidden.
4  * true: currently shown, false: currently hidden.
5  */
6 var showInfo = {};
8 /**
9  * Color to be used when highlighting the background of a row to indicate a change happened
10  */
11 var highlightColor = "#FFFF88";
13 /**
14  * Highlights a chatroom row during 3 seconds, in yellow color,
15  * in order to let the user see which booking was just created or modified.
16  */
17 var highlightChatroom = function(chatroom) {
18     IndicoUI.Effect.highLightBackground($E("chatroomRow" + chatroom.id), highlightColor, 3000);
19     var existingInfoRow = $E("infoRow" + chatroom.id);
20     if (existingInfoRow != null) {
21         IndicoUI.Effect.highLightBackground($E("infoRow" + chatroom.id), highlightColor, 3000);
22     }
25 /**
26  * @param {String} style The class name of the <ul> element inside this FoundPeopleList
27  *                       If left to null, it will be "UIPeopleList"
28  *
29  * @param {Function} selectionObserver A function that will be called when the selection varies. The function will be called without arguments
30  *                                     (it can use public methods of FoundPeopleList to get information).
31  *
32  * @param {Boolean} onlyOne If true, only 1 item can be selected at a time.
33  */
34 type ("ExistingChatroomsList", ["SelectableListWidget"],
35     {
36         _drawItem: function(pair) {
37             var self = this;
38             var elem = pair.get(); // elem is a WatchObject
39             var selected = false;
40             var id = Html.em({style: {paddingLeft: "5px", fontSize: '0.9em'}}, elem.get('id'));
41             var item = Html.div({},  elem.get('title') );
43             return item;
44         },
46         getList: function() {
47             return this.getSelectedList();
48         }
50     },
52     /**
53      * Constructor for FoundPeopleList
54      */
55     function(chatrooms, observer) {
56         var self = this;
57         this.selected = new WatchList();
59         this.SelectableListWidget(observer, false, 'chatList');
61         // Sort by name and add to the list
62         var items = {};
63         each(chatrooms, function(item) {
64             items[item.title + item.id] = item;
65         });
66         var ks = keys(items);
67         ks.sort();
69         for (k in ks) {
70             this.set(k, $O(items[ks[k]]));
71         }
72     }
78 type("AddChatroomDialog", ["ExclusivePopupWithButtons", "PreLoadHandler"],
79          {
80              _preload: [
81                  function(hook) {
82                      var self = this;
83                       self.chatrooms = [];
84                      var killProgress = IndicoUI.Dialogs.Util.progress($T("Fetching information..."));
85                      indicoRequest(
86                         'XMPP.getRoomsByUser',
87                         {
88                             usr: user
89                         },
90                         function(result,error) {
91                             if (!error) {
92                                 killProgress();
93                                 //we don't want to display the chat rooms that are already in the conference
94                                 if(result.length>0){
95                                     self.chatrooms = filter(result,function(chatroom){
96                                                          var notExists = true;
97                                                          each(chatroom.conferences, function(conf){
98                                                              if(conf == self.conf){
99                                                                  notExists = false;
100                                                              }
101                                                          });
102                                                          return notExists;
103                                                      });
104                                 }
105                                 self._processDialogState();
106                                 hook.set(true);
107                             } else {
108                                 killProgress();
109                                 IndicoUtil.errorReport(error);
110                             }
111                         }
112                     );
113                  }
114              ],
116              _processDialogState: function() {
117                  var self = this;
119                  if (this.chatrooms.length === 0) {
120                      // draw instead the creation dialog
121                      var dialog = createObject(
122                          ChatroomPopup,
123                          self.newArgs);
125                      dialog.open();
126                      dialog.postDraw();
128                      this.open = function() {};
130                      // exit, do not draw this dialog
131                      return;
132                  } else {
133                      this.ExclusivePopupWithButtons($T("Add Chat Room"),
134                                          function() {
135                                              self.close();
136                                          });
137                  }
139              },
141              existingSelectionObserver: function(selectedList) {
142                  if(selectedList.isEmpty()){
143                      this.saveButton.disabledButtonWithTooltip('disable');
144                  } else {
145                      this.saveButton.disabledButtonWithTooltip('enable');
146                  }
147              },
149              addExisting: function(rooms) {
150                  var self = this;
151                  var killProgress = IndicoUI.Dialogs.Util.progress();
152                  var args ={};
153                  args.rooms = rooms;
154                  args.conference = self.conf;
156                  indicoRequest('XMPP.addConference2Room', args,
157                                  function(result, error){
158                                    killProgress();
159                                     if (!error) {
160                                         // If the server found no problems, a chatroom object is returned in the result.
161                                         // We add it to the watchlist and create an iframe.
162                                         hideAllInfoRows(false);
163                                         showInfo[result.id] = true; // we initialize the show info boolean for this chatroom
164                                         each(result, function(cr){
165                                             links.set(cr.id, {});
166                                             links.get(cr.id)['custom'] = cr.custom;
167                                             if(showLogsLink){
168                                                 links.get(cr.id)['logs'] = cr.logs;
169                                             }
170                                             chatrooms.append(cr);
171                                         });
172                                         showAllInfoRows(false);
173                                         addIFrame(result);
174                                         refreshTableHead();
175                                         killProgress();
176                                         each(result, function(cr){
177                                             highlightChatroom(cr);
178                                         });
179                                         self.close();
180                                     } else {
181                                         killProgress();
182                                         self.close();
183                                         IndicoUtil.errorReport(error);
184                                     }
185                                   }
186                                );
187              },
189              draw: function() {
190                  var self = this;
192                  this.chatroomList = new ExistingChatroomsList(self.chatrooms, function(selectedList) {
193                      self.existingSelectionObserver(selectedList);
194                  });
195                  var content = Html.div({},
196                          $T("You may choose to:"),
197                          Html.ul({},
198                              Html.li({style:{marginBottom: '10px'}},
199                                  Widget.link(command(function() {
200                                      var dialog = createObject(ChatroomPopup, self.newArgs);
201                                      self.close();
202                                      dialog.open();
203                                      dialog.postDraw();
204                                  }, $T("Create a new chat room")))),
205                              Html.li({},
206                                  $T("Re-use one (or more) created by you"),
207                                  Html.div("chatListDiv",
208                                  this.chatroomList.draw()))));
210                  this.saveButton = self.buttons.eq(0);
211                  this.saveButton.disabledButtonWithTooltip({
212                      tooltip: $T('To add a chat room, please select at least one'),
213                      disabled: true
214                  });
216                  return this.ExclusivePopupWithButtons.prototype.draw.call(this, content);
217              },
219              _getButtons: function() {
220                  var self = this;
221                  return [
222                      [$T('Add selected'), function() {
223                          var ids = translate(self.chatroomList.getList().getAll(), function(chatroom) {
224                              return chatroom.getAll().id;
225                          });
226                          self.addExisting(ids);
227                      }]
228                  ];
229              }
230          },
231          function(conferenceId) {
232              var self = this;
234              this.conf = conferenceId;
235              this.newArgs = ['create', null, conferenceId];
237              this.PreLoadHandler(
238                  self._preload,
239                  function() {
240                      self.open();
241                  });
242              this.execute();
244          }
250  * -The chatroom parameters input by the user are retrieved with the "IndicoUtil.getFormValues" function.
251  *  -If modifying a chatroom, the already existing parameters will be taken from the chatroom object, and they will appear in the form
252  *  thanks to the "IndicoUtil.setFormValues" function.
253  * @param {string} popupType A string whose value should be 'create' or 'edit'
254  * @param {object} chatroom If 'create' mode, leave to null. If 'edit' mode, the chatroom object
255  * @param {string} conferenceId the conferenceId of the current event
256  */
257 type ("ChatroomPopup", ["ExclusivePopupWithButtons"],
258     {
259         switchToBasicTab: function() {
260             if (this.tabControl.getSelectedTab() === 'Advanced') {
261                 this.tabControl.setSelectedTab('Basic');
262             }
263         },
265         open: function() {
266             this.ExclusivePopupWithButtons.prototype.open.call(this);
267             disableCustomId(defaultHost);
268         },
270         draw: function() {
271             var self = this;
273             // We get the form HTML
274             var createCHRadioButton = Html.radio({id:"createCH", name:"createdInLocalServer"},true);
275             /* for some stupid reason, IE doesn't like that you directly put the value and assign the onclick event in the definition
276              * above, so it's necessary to do it 'manually'. Steve Ballmer, I hate you.
277              */
278             createCHRadioButton.dom.value = 'true';
279             createCHRadioButton.observeClick(function(){
280                                                 disableCustomId(defaultHost);
281                                              });
282             var createCHRadioButtonLabel = Html.label({style:{fontWeight:"normal"}}, $T("Default "));
283             createCHRadioButtonLabel.dom.htmlFor = "createCH";
285             var defineCHRadioButton = Html.radio({id:"defineCH", name:"createdInLocalServer"});
286             defineCHRadioButton.dom.value = 'false';
287             defineCHRadioButton.observeClick(function(){
288                                                 enableCustomId(customHost);
289                                              });
290             var defineCHRadioButtonLabel = Html.label({style:{fontWeight:"normal"}}, $T("Custom"));
291             defineCHRadioButtonLabel.dom.htmlFor = "defineCH";
293             var defineCHText = Html.edit({size:"35", name:"host", id:"host"});
294             this.parameterManager.add(defineCHText, 'text', false);
296             self.errorLabel=Html.label({style:{float: 'right', display: 'none'}, className: " invalid"}, $T('Name already in use'));
298             self.crName = new AutocheckTextBox({style: {width: '300px'}, name: 'title', id:"CRname"}, self.errorLabel);
299             //replace all the invalid characters
300             self.crName.set((conferenceName+eventDate).replace(/(\s)|\/|"|'|&|\\|:|<|>|@/g, "_"));
302             this.basicTabForm = Html.div({style:{textAlign: 'left'}},
303                 IndicoUtil.createFormFromMap([
304                 [$T('Server used'), Html.div({}, Html.tr({}, createCHRadioButton, createCHRadioButtonLabel), Html.tr({}, defineCHRadioButton, defineCHRadioButtonLabel))],
305                 [$T('Server'), defineCHText],
306                     [$T('Chat room name'), Html.td({},this.parameterManager.add(self.crName.draw(), 'text', false, function(text){
307                         // characters not admitted in XMPP standard. Check here in case of updates: http://xmpp.org/extensions/xep-0106.html
308                         if(text.indexOf(' ') != -1 ||
309                            text.indexOf('\'') != -1 ||
310                            text.indexOf('\"') != -1 ||
311                            text.indexOf('&') != -1 ||
312                            text.indexOf('/') != -1 ||
313                            text.indexOf(':') != -1 ||
314                            text.indexOf('<') != -1 ||
315                            text.indexOf('>') != -1 ||
316                            text.indexOf('@') != -1){
317                             return Html.span({}, $T("You introduced an invalid character in the name, don't use spaces, \', \", &, /, :, <, > or @"));
318                         }
319                     }), self.errorLabel)],
320                     [$T('Description'), Html.textarea({cols: 40, rows: 2, name: 'description', id:'description'}) ]
321                 ])
322             );
324             var showCH = Html.checkbox({id:"showCH"}, true);
325             //You don't like this? Me neither. Give thanks to Bill Gates and IE *sigh*
326             showCH.dom.name = "showRoom";
327             var showPwd = Html.checkbox({id:"showPwd"}, false);
328             showPwd.dom.name = "showPass";
330             var passwordField = new ShowablePasswordField('roomPass', '', false, 'CHpass').draw();
331             this.advancedTabForm = Html.div({},
332                 IndicoUtil.createFormFromMap([
333                     [$T('Password'), passwordField  ]]),
334                 Html.div({className: 'chatAdvancedTabTitleLine', style: {marginTop:pixels(10)}},
335                         Html.div({className: 'chatAdvancedTabTitle'}, $T('Information displayed in the event page'))
336                         ),
337                 IndicoUtil.createFormFromMap([
338                     [Html.div({className: 'chatAdvancedTabCheckboxDiv', style: {marginTop:pixels(5)}},
339                             Html.tr({},
340                                 showCH,
341                                 $T('Show chat room information to the users')
342                             ),
343                             Html.tr({},
344                                 showPwd,
345                                 $T('Show the chat room\'s password to the users ')
346                             ))
347                     ]
348                 ])
349             );
351             var width = 600;
352             var height = 200
354             this.tabControl = new JTabWidget([[$T("Basic"), this.basicTabForm], [$T("Advanced"), this.advancedTabForm]], width, height);
355             return this.ExclusivePopupWithButtons.prototype.draw.call(this, this.tabControl.draw());
356         },
358         _getButtons: function() {
359             var self = this;
360             return [
361                 [$T('Save'), function() {
362                     self.__save();
363                 }],
364                 [$T('Cancel'), function() {
365                     self.close();
366                 }]
367             ];
368         },
370         postDraw: function() {
371             var self = this
373             if (self.popupType === 'edit') {
374                 setValues(self.chatroom);
375                 if(!self.chatroom.createdInLocalServer){
376                     enableCustomId(customHost);
377                 }
378                 else{
379                     disableCustomId(defaultHost);
380                 }
381             }
383             self.tabControl.heightToTallestTab();
384             self.ExclusivePopupWithButtons.prototype.postDraw.call(this);
385         },
388         addComponent: function(component) {
389             this.components.push(component);
390             this.parameterManager.add(component);
391         },
393         __save: function(){
394             var self = this;
395             values = getValues();
397             // We check if there are errors
398             var checkOK = this.parameterManager.check();
400             // If there are no errors, the chat room is sent to the server
401             if (checkOK) {
402                 var killProgress = IndicoUI.Dialogs.Util.progress($T("Saving your chatroom..."));
404                     if (this.popupType === 'create') {
405                         indicoRequest(
406                             'XMPP.createRoom',
407                             {
408                                 conference: this.conferenceId,
409                                 chatroomParams: values
410                             },
411                             function(result,error) {
412                                 if (!error) {
413                                     // If the server found no problems, a chat room object is returned in the result.
414                                     // We add it to the watchlist and create an iframe.
415                                     hideAllInfoRows(false);
416                                     showInfo[result.id] = true; // we initialize the show info boolean for this chat room
417                                     links.set(result.id, {});
418                                     links.get(result.id)['custom'] = result.custom;
419                                     if(showLogsLink){
420                                         links.get(result.id)['logs'] = result.logs;
421                                     }
422                                     chatrooms.append(result);
423                                     showAllInfoRows(false);
424                                     addIFrame(result);
425                                     refreshTableHead();
426                                     killProgress();
427                                     highlightChatroom(result);
428                                     self.close();
429                                 } else {
430                                     if(error.explanation == 'roomExists'){
431                                         killProgress();
432                                         self.crName.startWatching(true);
433                                     }
434                                     else{
435                                         killProgress();
436                                         self.close();
437                                         IndicoUtil.errorReport(error);
438                                     }
439                                 }
440                             }
441                         );
443                     } else if (this.popupType === 'edit') {
444                         values.id = this.chatroom.id;
445                         indicoRequest(
446                                 'XMPP.editRoom',
447                             {
448                                 conference: this.conferenceId,
449                                 chatroomParams: values
450                             },
451                             function(result,error) {
452                                 if (!error) {
453                                     showInfo[result.id] = true;
454                                     refreshChatroom(result);
455                                     killProgress();
456                                     self.close();
457                                 } else {
458                                     if(error.explanation == 'roomExists'){
459                                         killProgress();
460                                         self.crName.startWatching(true);
461                                     }
462                                     else{
463                                         killProgress();
464                                         self.close();
465                                         IndicoUtil.errorReport(error);
466                                     }
467                                 }
468                             }
469                         );
470                     }
472             } else { // Parameter manager detected errors
473                 this.switchToBasicTab();
474             }
475         },
477     },
479     /**
480      * Constructor
481      */
482     function(popupType, chatroom, conferenceId) {
483         this.popupType = popupType;
484         if (popupType === 'create') {
485             var title = $T(" Chat room creation");
486         } else if (popupType === 'edit') {
487             this.chatroom = chatroom;
488             var title = $T(' Chat room modification');
489         }
491         this.conferenceId = conferenceId;
492         customHost = chatroom && !chatroom.createdInLocalServer? chatroom.host:'';
493         this.ExclusivePopupWithButtons(title, positive);
495         this.parameterManager = new IndicoUtil.parameterManager();
497         if(popupType === 'edit'){
498             this.chatroomID = chatroom.id
499         }
500     }
504 type("LogPopup", ["ExclusivePopupWithButtons"],
505     {
506          draw: function() {
507              return this.ExclusivePopupWithButtons.prototype.draw.call(this, this.content);
508          },
510          _getButtons: function() {
511              var self = this;
512              return [
513                  [$T('OK'), function() {
514                      var result = self.handler(true);
515                      if (result){
516                          window.location = result;
517                          self.close();
518                      }
519                  }],
520                  [$T('Cancel'), function() {
521                      self.handler(false);
522                      self.close();
523                  }]
524              ];
525          }
526     },
528     function(title, content, handler) {
529         var self = this;
531         this.content = content;
532         this.handler = handler;
533         this.ExclusivePopupWithButtons(title, function(){
534             self.handler(false);
535             return true;
536         });
537     }
542 * Utility function to "refresh" the display of a chat room and show its updated value if it changed.
544 var refreshChatroom = function(chatroom, doHighlight) {
545     doHighlight = any(doHighlight, true);
546     var index = getChatroomIndexById(chatroom.id);
547     hideAllInfoRows(false);
548     chatrooms.removeAt(index);
549     chatrooms.insert(chatroom, index+"");
550     showAllInfoRows(false);
551     if (doHighlight) {
552         highlightChatroom(chatroom);
553     }
556 var enableCustomId = function(newHost) {
557     if ($E('host') != null){
558         $E('host').set(newHost);
559         IndicoUI.Effect.enableDisableTextField($E('host'), true);
560     }
563 var disableCustomId = function(newHost) {
564     if ($E('host') != null){
565         $E('host').set(newHost);
566         IndicoUI.Effect.enableDisableTextField($E('host'), false);
567     }
571  * Given a chat room id, it returns the index of the chat room with that id in the "var chatrooms = $L();" object.
572  * Example: chat rooms is a Watchlist of chat room object who ids are [1,2,10,12].
573  *          getchatroomIndexById('10') will return 2.
574  * @param {String} id The id of a chat room object.
575  * @return {int} the index of the chat room object with the given id, inside the watchlist "chatrooms".
576  */
577 var getChatroomIndexById = function(id) {
578     for (var i=0; i < chatrooms.length.get(); i++) {
579         chatroom = chatrooms.item(i);
580         if (chatroom.id == id) {
581             return i;
582         }
583     }
586 var showInfo = function(chatroom) {
587     var infoTbody = Html.tbody();
588     if (chatroom.error && chatroom.errorDetails) {
589         var errorCell = Html.td({colspan:2, colSpan:2});
590         errorCell.append(Html.span('collaborationWarning', chatroom.errorDetails));
591         infoTbody.append(Html.tr({}, errorCell));
592     }
594     infoTbody.append(Html.tr({},
595         Html.td("chatInfoLeftCol", $T('Room name:')),
596         Html.td({}, chatroom.title)));
598     infoTbody.append(Html.tr({},
599             Html.td("chatInfoLeftCol", $T('Host:')),
600             Html.td({}, chatroom.createdInLocalServer?'conference.'+chatroom.host:chatroom.host)));
602     infoTbody.append(Html.tr({},
603         Html.td("chatInfoLeftCol", $T('Description:')),
604         Html.td({}, chatroom.description)));
606     infoTbody.append(Html.tr({},
607         Html.td("chatInfoLeftCol", $T('Created by:')),
608         Html.td({}, chatroom.owner.name)));
610     infoTbody.append(Html.tr({},
611             Html.td("chatInfoLeftCol", $T('Show chat room:')),
612             Html.td({}, chatroom.showRoom?$T('Yes'):$T('No'))));
614     infoTbody.append(Html.tr({},
615             Html.td("chatInfoLeftCol", $T('Created in local XMPP server:')),
616             Html.td({}, chatroom.createdInLocalServer?$T('Yes'):$T('No'))));
618     infoTbody.append(Html.tr({},
619             Html.td("chatInfoLeftCol", $T('Show password to users:')),
620             Html.td({}, chatroom.showPass?$T('Yes'):$T('No'))));
622     infoTbody.append(Html.tr({},
623             Html.td("chatInfoLeftCol", $T('Password:')),
624             Html.td({}, new HiddenText(chatroom.password, "*********",false).draw())));
626     var day = chatroom.creationDate.date.slice(8,10);
627     var month = chatroom.creationDate.date.slice(5,7);
628     var year = chatroom.creationDate.date.slice(0,4);
629     infoTbody.append(Html.tr({},
630             Html.td("chatInfoLeftCol", $T('Date of creation:')),
631             Html.td({},
632                     Html.tr({},day+'-'+month+'-'+year),
633                     Html.tr({},chatroom.creationDate.time.slice(0,8)  )
634                     )
635     ));
637     if(chatroom.modificationDate){
638         day = chatroom.modificationDate.date.slice(8,10);
639         month = chatroom.modificationDate.date.slice(5,7);
640         year = chatroom.modificationDate.date.slice(0,4);
641         infoTbody.append(Html.tr({},
642                 Html.td("chatInfoLeftCol", $T('Last modification:')),
643                 Html.td({},
644                         Html.tr({},day+'-'+month+'-'+year),
645                         Html.tr({},chatroom.modificationDate.time.slice(0,8))
646                         )));
647     }
649     infoTbody.append(Html.tr({},
650             Html.td("chatInfoLeftCol", $T(' Timezone: ')),
651             Html.td({},timeZone)
652         ));
654     return Html.div({}, Html.table({}, infoTbody));
657 var checkCRStatus = function(chatroom){
658     arrangeRoomData(chatroom);
660     var killProgress = IndicoUI.Dialogs.Util.progress($T("Requesting..."));
661     indicoRequest(
662             'XMPP.getRoomPreferences',
663         {
664             conference: conferenceID,
665             chatroomParams: chatroom
666         },
667         function(result,error) {
668             if (!error) {
669                 showInfo[result.id] = true;
670                 refreshChatroom(result);
671                 killProgress();
672             } else {
673                 killProgress();
674                 IndicoUtil.errorReport(error);
675             }
676         }
677     );
681  * Builds a table row element from a chat room object, pickled from an Indico's CSchatroom object
682  * @param {Object} chatroom A chatroom object.
683  * @return {XElement} an Html.row() XElement with the row representing the chat room.
684  */
685 var chatroomTemplate = function(chatroom) {
686     var row = Html.tr({id: "chatroomRow" + chatroom.id});
688     var cellShowInfo = Html.td({className : "chatCellNarrow"});
689     showInfoButton = IndicoUI.Buttons.customImgSwitchButton(
690             showInfo[chatroom.id],
691             Html.img({
692                 alt: "Show info",
693                 src: imageSrc("itemExploded"),
694                 className: "centeredImg"
695             }),
696             Html.img({
697                 alt: "Hide info",
698                 src: imageSrc("currentMenuItem"),
699                 className: "centeredImg"
700             }),
701             chatroom, showChatroomInfo, showChatroomInfo
702     );
703     cellShowInfo.set(showInfoButton);
705     row.append(cellShowInfo);
708     var completeHost = chatroom.createdInLocalServer?'conference.'+chatroom.host:chatroom.host;
709     var cellCustom = Html.td({className : "chatCell"});
710         cellCustom.dom.innerHTML = chatroom.title + ' (@' + completeHost + ')';
712     row.append(cellCustom);
714     var cellEditRemove = Html.td({className : "chatCell"});
715     var editButton = Widget.link(command(function(){edit(chatroom);}, IndicoUI.Buttons.editButton()));
716     var removeButton = Widget.link(command(function(){remove(chatroom);}, IndicoUI.Buttons.removeButton()));
719     cellEditRemove.append(editButton);
720     cellEditRemove.append(removeButton);
721     if(chatroom.createdInLocalServer){
722         var checkStatusButton = Widget.link(command(
723                 function() {checkStatus(chatroom);} ,
724                 Html.img({
725                     alt: $T("Refresh chat room data"),
726                     title: $T("Refresh chat room data"),
727                     src: imageSrc("reload"),
728                     style: {
729                         'verticalAlign': 'middle'
730                     }
731                 })
732             ));
733     }
734     else{
735         var checkStatusButton =
736                 Html.img({
737                     alt: $T("Refresh not available in external servers"),
738                     title: $T("Refresh not available in external servers"),
739                     src: imageSrc("reload_faded"),
740                     style: {
741                         'verticalAlign': 'middle'
742                     }
743                 });
744     }
745     cellEditRemove.append(checkStatusButton);
746     row.append(cellEditRemove);
748     if(links.get(chatroom.id).custom){
749         var joinNow = Html.td({id:"joinLink", name:"joinLink", className : "dropDownMenu highlight", style:{fontWeight: "bold", whiteSpace: "nowrap"}}, Html.a({href: "#"}, $T("Join now!")) );
750         row.append(joinNow);
751         showLinkMenu(joinNow, chatroom);
752     }
754     if(links.get(chatroom.id).custom && chatroom.createdInLocalServer && links.get(chatroom.id) && showLogsLink){
755         var sepBar = Html.td({style:{fontWeight: "bold", whiteSpace: "nowrap"}}, " | ");
756         row.append(sepBar);
757     }
759     if(chatroom.createdInLocalServer && links.get(chatroom.id) && showLogsLink){
760         var logs = Html.td({id:"logsLink", name:"logsLink", className : "dropDownMenu highlight", style:{fontWeight: "bold", whiteSpace: "nowrap"}}, Html.a({href: "#"}, $T("Logs")) );
761         row.append(logs);
762         showLogOptions(logs, chatroom);
763     }
765     return row;
768 var showLinkMenu = function(element, chatroom){
769     var joinLink = $E('joinLink');
770     var joinMenu = null;
771     if(element){
772         element.observeClick(function(e) {
773             // Close the menu if clicking the link when menu is open
774             if (joinMenu != null && joinMenu.isOpen()) {
775                 joinMenu.close();
776                 joinMenu = null;
777                 return;
778             }
779             var menuItems = {};
781             each(links.get(chatroom.id).custom, function(linkType){
782                 menuItems['Using ' + linkType.name] = linkType.link;
783             });
784             joinMenu = new PopupMenu(menuItems, [element], 'categoryDisplayPopupList', true, false, null, null, true);
785             var pos = element.getAbsolutePosition();
786             joinMenu.open(pos.x - 5, pos.y + element.dom.offsetHeight + 2);
787             return false;
788         });
789     }
792 var createBaseForm = function(){
793     var startDate = new DateTimeSelector();
794     var endDate = new DateTimeSelector();
796     var getAll = Html.radio({id:"getall", name:"rangetype"});
797     getAll.observe(function(value){
798         if (value){
799             startDate.disable();
800             endDate.disable();
801         }
802     });
803     var forEvent = Html.radio({id:"forevent", name:"rangetype"}, true);
804     forEvent.observe(function(value){
805         if (value){
806             startDate.disable();
807             endDate.disable();
808         }
809     });
810     var ownRange = Html.radio({id:"ownrange", name:"rangetype"});
811     ownRange.observe(function(value){
812         if (value){
813             startDate.enable();
814             endDate.enable();
815         }
816     });
817     startDate.disable();
818     endDate.disable();
820     var content = Html.div({style: {marginTop:pixels(7), marginBottom:pixels(7)}},
821                         Html.div({style: {marginTop:pixels(5)}}, forEvent, $T('Get logs for this chat room in this event') ),
822                         Html.div({style: {marginTop:pixels(5)}}, getAll, $T('Get the logs for this chat room in this event and the past ones') ),
823                         Html.div({style: {marginTop:pixels(8)}}, ownRange, $T('Create your own range')),
824                         Html.div(   {style: {marginLeft:pixels(10),marginTop:pixels(15), marginBottom:pixels(5)}},
825                                     Html.span({style: {marginRight:pixels(10)}}, $T("from")),
826                                     startDate.draw(),
827                                     Html.span({style: {margin:pixels(10)}}, $T("to")),
828                                     endDate.draw()
829                                  )
830                       );
831     return {'content': content, 'sdate': startDate, 'edate': endDate, 'getall': getAll, 'forevent': forEvent, 'ownrange': ownRange};
834 var showLogOptions = function(element, chatroom){
835     var logsLink = $E('logsLink');
836     var logsMenu = null;
837     if(element){
838         element.observeClick(function(e) {
839             // Close the menu if clicking the link when menu is open
840             if (logsMenu != null && logsMenu.isOpen()) {
841                 logsMenu.close();
842                 logsMenu = null;
843                 return;
844             }
845             var menuItems = {};
847             var form = createBaseForm();
849             menuItems[$T('See logs')] = new LogPopup($T('Select the dates to retrieve the logs'),
850                                                  form.content,
851                                                  function(value){
852                                                     if (value){
853                                                         // replace all the / with - to avoid problems in the URL
854                                                         return buildLogURL(chatroom,
855                                                                           form.sdate.get()?form.sdate.get().replace(/\//g,"-"):null,
856                                                                           form.edate.get()?form.edate.get().replace(/\//g,"-"):null,
857                                                                           form.getall.get(),
858                                                                           form.forevent.get(),
859                                                                           form.ownrange.get());
860                                                      }
861                                                  });
862             var parameterManager = new IndicoUtil.parameterManager();
864             var form2 = createBaseForm();
865             var materialName = Html.input('text',{style: {marginLeft:pixels(7)}});
866             parameterManager.add(materialName, 'text', false);
867             var materialContent = form2.content
868             materialContent.addContent(Html.div({style: {fontWeight: "bold", maxWidth:pixels(500),marginTop:pixels(25)}},
869                                        $T('Have in mind that due to security policy logs will be private. If you want to change the protection level you will have to do it manually.'))
870                                       );
871             materialContent.addContent(Html.div({style: {float: 'right',marginTop:pixels(10)}},
872                                        $T("Material name"),
873                                        materialName)
874                                       );
875             var requestOk = false;
876             menuItems[$T('Attach logs to event material')] = new LogPopup($T('Select the name that logs will have in the material section'),
877                                                                       materialContent,
878                                                                       function(value){
879                                                                           if(value){
880                                                                               checkOk = parameterManager.check();
881                                                                               if(checkOk){
882                                                                                   var killProgress = IndicoUI.Dialogs.Util.progress($T("Adding..."));
883                                                                                   // make ajax request
884                                                                                   indicoRequest(
885                                                                                           'XMPP.attachLogs',
886                                                                                           {
887                                                                                               confId: conferenceID,
888                                                                                               crId: chatroom.id,
889                                                                                               sdate: form2.sdate.get()?form2.sdate.get().replace(/\//g,"-"):null,
890                                                                                               edate: form2.edate.get()?form2.edate.get().replace(/\//g,"-"):null,
891                                                                                               getAll: form2.getall.get(),
892                                                                                               forEvent: form2.forevent.get(),
893                                                                                               matName: materialName.get()
894                                                                                           },
895                                                                                           function(result,error) {
896                                                                                               if (error) {
897                                                                                                   killProgress();
898                                                                                                   IndicoUtil.errorReport(error);
899                                                                                               }
900                                                                                               else{
901                                                                                                   killProgress();
903                                                                                                   // the handler will return a value before this request ends,
904                                                                                                   // so we need to manually change the window location
905                                                                                                   window.location = materialUrl+'#'+result;
906                                                                                                   return materialUrl+'#'+result;
907                                                                                               }
908                                                                                           }
909                                                                                       );
910                                                                                }
911                                                                               else return false;
912                                                                            }
913                                                                       });
914             logsMenu = new PopupMenu(menuItems, [element], 'categoryDisplayPopupList', true);
915             var pos = element.getAbsolutePosition();
916             logsMenu.open(pos.x - 5, pos.y + element.dom.offsetHeight + 2);
917             return false;
918         });
919     }
922 var buildLogURL = function(chatroom, sdate, edate, selectAll, forEvent, ownRange){
923     /* Builds the url to make the request to web.py and get the logs
924      * sdate and edate: range of dates to get the logs
925      * selectAll: we want to retrieve all the logs for the chat room
926      * forEvent: we want to retrieve the logs for the current event
927      * ownRange: we want to specify the range of dates
928      */
929     url = links.get(chatroom.id).logs;
930     if (selectAll){
931         return url;
932     }
933     else if (forEvent){
934         url += '&forEvent=true';
935         return url;
936     }
937     else if (ownRange){
938         if ( sdate && !edate){
939             url += '&sdate=' + sdate;
940         }
941         else if ( !sdate && edate){
942             url += '&edate=' + edate;
943         }
944         else if (sdate && edate){
945             url += '&sdate=' + sdate + '&edate=' + edate;
946         }
947     }
948     return url;
952  * -Function that will be called when the user presses the "Show" button of a chat room.
953  * -A new row will be created in the table of chat rooms in order to show this information.
954  * -Drawback: the row will be destroyed when a new chat room is added or a chat room is edited.
955  */
956 var showChatroomInfo = function(chatroom) {
957     if (showInfo[chatroom.id]) { // true if info already being shown
958         hideInfoRow(chatroom);
959     } else { // false if we have to show it
960         showInfoRow(chatroom);
961     }
962     showInfo[chatroom.id] = !showInfo[chatroom.id];
966  * Hides all of the information rows
967  * @param {boolean} markAsHidden If true, the rows will be marked as hidden in the showInfo object
968  */
969 var hideAllInfoRows = function(markAsHidden) {
970     chatrooms.each(function(chatroom) {
971         hideInfoRow(chatroom);
972         if (markAsHidden) {
973             showInfo[chatroom.id] = false;
974         }
975     });
979  * Hides all of the information rows
980  * @param {boolean} showAll If true, all the rows will be shown. Otherwise, only those marked as shown in the showInfoObject
981  */
982 var showAllInfoRows = function(showAll) {
983     chatrooms.each(function(chatroom) {
984         if (showAll || showInfo[chatroom.id]) {
985             showInfoRow(chatroom);
986             showInfo[chatroom.id] = true;
987         }
988     });
992  * Hides the information text of a chat room by removing its row from the table
993  */
994 var hideInfoRow = function (chatroom) {
995     var existingInfoRow = $E("infoRow" + chatroom.id);
996     if (existingInfoRow != null) {
997         IndicoUI.Effect.disappear(existingInfoRow);
998         $E('chatroomsTableBody').remove(existingInfoRow);
999     } //otherwise ignore
1003  * Shows the information text of a chat room by adding its row to the table and updating it
1004  */
1005 var showInfoRow = function(chatroom) {
1006     var newRow = Html.tr({id: "infoRow" + chatroom.id, display: "none"} );
1007     var newCell = Html.td({id: "infoCell" + chatroom.id, colspan: 16, colSpan: 16, className : "chatInfoCell"});
1008     newRow.append(newCell);
1009     var nextRowDom = $E('chatroomRow'+chatroom.id).dom.nextSibling;
1010     if (nextRowDom) {
1011         $E('chatroomsTableBody').dom.insertBefore(newRow.dom, nextRowDom);
1012     } else {
1013         $E('chatroomsTableBody').append(newRow);
1014     }
1015     updateInfoRow(chatroom);
1016     IndicoUI.Effect.appear(newRow, '');
1020  * Sets the HTML inside the information text of a chat room
1021  */
1022 var updateInfoRow = function(chatroom) {
1023     var existingInfoCell = $E("infoCell" + chatroom.id);
1024     if (existingInfoCell != null) { // we update
1025         var infoHTML = showInfo(chatroom);
1026         if (isString(infoHTML)) {
1027             existingInfoCell.dom.innerHTML = infoHTML;
1028         } else if(infoHTML.XElement) {
1029             existingInfoCell.set(infoHTML);
1030         }
1031     } //otherwise ignore
1035  * Requests the list of chat rooms from the server,
1036  * and put them into the "chat rooms" watchlist.
1037  * As a consequence the chat rooms table where 1 chat room = 1 row is initialized.
1038  */
1039 var displayChatrooms = function() {
1040     var killProgress = IndicoUI.Dialogs.Util.progress($T("Loading list of chatrooms..."));
1041     // We bind the watchlist and the table through the template
1042     bind.element($E("chatroomsTableBody"), chatrooms, chatroomTemplate);
1043     each(chatrooms, function(chatroom) {
1044         addIFrame(chatroom);
1045     });
1046     refreshTableHead();
1047     killProgress();
1050 var refreshTableHead = function() {
1051     var length = chatrooms.length.get();
1052     var headRow = $E('tableHeadRow');
1053     if (length == 0) {
1054         var cell = Html.td();
1055         cell.set(Html.span('',$T('Currently no chatrooms have been created')));
1056         headRow.set(cell);
1057     } else {
1058         headRow.clear();
1060         var firstCell = Html.td();
1061         headRow.append(firstCell);
1063         var emptyCell = Html.td({className: "collaborationTitleCell"});
1064         headRow.append(emptyCell);
1066         var lastCell = Html.td({width: "100%", colspan: 1, colSpan: 1})
1067         headRow.append(lastCell);
1068     }
1072  * Utility function to add an iframe inside the 'iframes' div element, given a chatroom.
1073  * The chatroom id is used to name the iframe.
1074  * Each chatroom will have a corresponding iframe that will be using when, for example, loading an URL,
1075  * @param {object} chatroom A chatroom object.
1076  */
1077 var addIFrame = function(chatroom) {
1078     var iframeName = "iframeTarget" + chatroom.id;
1079     var iframe = Html.iframe({id: iframeName, name: iframeName, src:"", style:{display: "block"}});
1080     $E('iframes').append(iframe);
1084   * Utility function to remove an iframe inside the 'iframes' div element, given a chatroom.
1085   * The chatroom id is used to find the iframe to remove.
1086   * @param {object} chatroom A chatroom object.
1087   */
1088 var removeIFrame = function(chatroom) {
1089     var iframeName = "iframeTarget" + chatroom.id;
1090     $E('iframes').remove($E(iframeName));
1095 var createChatroom = function(conferenceId) {
1096     var popup = new AddChatroomDialog(conferenceId);
1097     return true;
1100 var arrangeRoomData = function(chatroom){
1101     chatroom.showRoom.checked = chatroom.showRoom;
1102     chatroom.showPass.checked = chatroom.showPass;
1103     chatroom.createdInLocalServer.checked = chatroom.createdInLocalServer;
1104     chatroom.createdInLocalServer?chatroom.host = defaultHost:chatroom.host = chatroom.host;
1108  * @param {object} chatroom The chatroom object corresponding to the "edit" button that was pressed.
1109  * @param {string} conferenceId the conferenceId of the current event
1110  */
1111 var editChatroom = function(chatroom, conferenceId) {
1112     arrangeRoomData(chatroom);
1114     var popup = new ChatroomPopup('edit', chatroom, conferenceId);
1115     popup.open();
1116     popup.postDraw();
1119 var removeChatroom = function(chatroom, conferenceId) {
1121     var confirmHandler = function(confirm) { if (confirm) {
1123         var killProgress = IndicoUI.Dialogs.Util.progress($T("Removing your chat room..."));
1125         arrangeRoomData(chatroom);
1127         indicoRequest(
1128             'XMPP.deleteRoom',
1129             {
1130                 conference: conferenceId,
1131                 chatroomParams: chatroom
1132             },
1133             function(result,error) {
1134                 if (!error) {
1135                     // If the server found no problems, we remove the chatroom from the watchlist and remove the corresponding iframe.
1136                     if (result && result.error) {
1137                         killProgress();
1138                     } else {
1139                         hideAllInfoRows(false);
1140                         chatrooms.removeAt(getChatroomIndexById(chatroom.id))
1141                         showAllInfoRows(false);
1142                         removeIFrame(chatroom);
1143                         refreshTableHead();
1144                     }
1145                     killProgress();
1146                 } else {
1147                     killProgress();
1148                     IndicoUtil.errorReport(error);
1149                 }
1150             }
1151         );
1152     }};
1154     IndicoUI.Dialogs.Util.confirm($T("Remove chat room"),
1155             Html.div({style:{paddingTop:pixels(10), paddingBottom:pixels(10)}}, $T("Are you sure you want to remove that ") + $T(" chat room?")),
1156             confirmHandler);
1159 var getValues = function(){
1160     return {  'title': $E('CRname').dom.value,
1161             'createdInLocalServer': $E('createCH').dom.checked,
1162             'host': $E('host').dom.value,
1163             'description': $E('description').dom.value,
1164             'roomPass': $E('CHpass').dom.value,
1165             'showRoom': $E('showCH').dom.checked,
1166             'showPass': $E('showPwd').dom.checked
1167          };
1170 var setValues = function(chatroom){
1171     $E('CRname').dom.value = chatroom.title;
1172     $E('createCH').dom.checked = chatroom.createdInLocalServer;
1173     $E('defineCH').dom.checked = !chatroom.createdInLocalServer;
1174     $E('host').dom.value = chatroom.host;
1176     $E('description').dom.value = chatroom.description;
1177     $E('CHpass').dom.value = chatroom.password;
1178     $E('showCH').dom.checked = chatroom.showRoom;
1179     $E('showPwd').dom.checked = chatroom.showPass;