Browse Source

Implements audio and visual chat notifications. Closes issue #7. Implements audio notifications for people joining and leaving. Closes issue #37.

master
yanas 11 years ago
parent
commit
ee5936aaef
10 changed files with 340 additions and 164 deletions
  1. 13
    143
      app.js
  2. 222
    0
      chat.js
  3. 42
    13
      css/main.css
  4. 4
    2
      etherpad.js
  5. 15
    5
      index.html
  6. 1
    1
      muc.js
  7. BIN
      sounds/incomingMessage.wav
  8. BIN
      sounds/joined.wav
  9. BIN
      sounds/left.wav
  10. 43
    0
      util.js

+ 13
- 143
app.js View File

@@ -182,6 +182,8 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
182 182
         container = document.createElement('span');
183 183
         container.className = 'videocontainer';
184 184
         remotes.appendChild(container);
185
+        console.log("PLAY USER JOINEDDDDDDDD");
186
+        Util.playSoundNotification('userJoined');
185 187
     }
186 188
     var vid = document.createElement('video');
187 189
     var id = 'remoteVideo_' + sid + '_' + data.stream.id;
@@ -212,11 +214,12 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
212 214
             if (pick) {
213 215
                  if (pick.src === localVideoSrc)
214 216
                  isLocalVideo = true;
215
-                 
217
+
216 218
                  updateLargeVideo(pick.src, isLocalVideo, pick.volume);
217 219
             }
218 220
         }
219 221
         $('#' + id).parent().remove();
222
+        Util.playSoundNotification('userLeft');
220 223
         resizeThumbnails();
221 224
     };
222 225
     sel.click(
@@ -632,8 +635,8 @@ function toggleAudio() {
632 635
     }
633 636
 }
634 637
 
635
-function resizeLarge() {
636
-    resizeChat();
638
+var resizeLarge = function () {
639
+    Chat.resizeChat();
637 640
     var availableHeight = window.innerHeight;
638 641
     var chatspaceWidth = $('#chatspace').is(":visible")
639 642
                             ? $('#chatspace').width()
@@ -666,7 +669,7 @@ function resizeLarge() {
666 669
     }
667 670
 
668 671
     resizeThumbnails();
669
-}
672
+};
670 673
 
671 674
 function resizeThumbnails() {
672 675
     // Calculate the available height, which is the inner window height minus 39px for the header
@@ -691,70 +694,8 @@ function resizeThumbnails() {
691 694
     $('#remoteVideos>span').height(availableHeight);
692 695
 }
693 696
 
694
-function resizeChat() {
695
-    var availableHeight = window.innerHeight;
696
-    var availableWidth = window.innerWidth;
697
-
698
-    var chatWidth = 200;
699
-    if (availableWidth*0.2 < 200)
700
-        chatWidth = availableWidth*0.2;
701
-
702
-    $('#chatspace').width(chatWidth);
703
-    $('#chatspace').height(availableHeight - 40);
704
-
705
-    resizeChatConversation();
706
-}
707
-
708
-function resizeChatConversation() {
709
-    var usermsgStyleHeight = document.getElementById("usermsg").style.height;
710
-    var usermsgHeight = usermsgStyleHeight.substring(0, usermsgStyleHeight.indexOf('px'));
711
-
712
-    $('#chatconversation').width($('#chatspace').width() - 10);
713
-    $('#chatconversation').height(window.innerHeight - 50 - parseInt(usermsgHeight));
714
-}
715
-
716 697
 $(document).ready(function () {
717
-    var storedDisplayName = window.localStorage.displayname;
718
-    if (storedDisplayName) {
719
-        nickname = storedDisplayName;
720
-
721
-        setChatConversationMode(true);
722
-    }
723
-
724
-    $('#nickinput').keydown(function(event) {
725
-        if (event.keyCode == 13) {
726
-            event.preventDefault();
727
-            var val = this.value;
728
-            this.value = '';
729
-            if (!nickname) {
730
-                nickname = val;
731
-                window.localStorage.displayname = nickname;
732
-
733
-                connection.emuc.addDisplayNameToPresence(nickname);
734
-                connection.emuc.sendPresence();
735
-
736
-                setChatConversationMode(true);
737
-
738
-                return;
739
-            }
740
-        }
741
-    });
742
-
743
-    $('#usermsg').keydown(function(event) {
744
-        if (event.keyCode == 13) {
745
-            event.preventDefault();
746
-            var message = this.value;
747
-            $('#usermsg').val('').trigger('autosize.resize');
748
-            this.focus();
749
-            connection.emuc.sendMessage(message, nickname);
750
-        }
751
-    });
752
-
753
-    var onTextAreaResize = function() {
754
-        resizeChatConversation();
755
-        scrollChatToBottom();
756
-    };
757
-    $('#usermsg').autosize({callback: onTextAreaResize});
698
+    Chat.init();
758 699
 
759 700
     // Set the defaults for prompt dialogs.
760 701
     jQuery.prompt.setDefaults({persistent: false});
@@ -826,24 +767,6 @@ function dump(elem, filename){
826 767
     return false;
827 768
 }
828 769
 
829
-/*
830
- * Appends the given message to the chat conversation.
831
- */
832
-function updateChatConversation(nick, message)
833
-{
834
-    var divClassName = '';
835
-    if (nickname == nick)
836
-        divClassName = "localuser";
837
-    else
838
-        divClassName = "remoteuser";
839
-
840
-    //replace links and smileys
841
-    message = processReplacements(message);
842
-
843
-    $('#chatconversation').append('<div class="' + divClassName + '"><b>' + nick + ': </b>' + message + '</div>');
844
-    $('#chatconversation').animate({ scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
845
-}
846
-
847 770
 /*
848 771
  * Changes the style class of the element given by id.
849 772
  */
@@ -1092,44 +1015,6 @@ function updateLockButton() {
1092 1015
     buttonClick("#lockIcon", "fa fa-unlock fa-lg fa fa-lock fa-lg");
1093 1016
 }
1094 1017
 
1095
-/*
1096
- * Opens / closes the chat area.
1097
- */
1098
-function openChat() {
1099
-    var chatspace = $('#chatspace');
1100
-    var videospace = $('#videospace');
1101
-
1102
-    var onShow = function () {
1103
-        resizeLarge();
1104
-        $('#chatspace').show("slide", { direction: "right", duration: 500});
1105
-    };
1106
-    var onHide = function () {
1107
-        $('#chatspace').hide("slide", { direction: "right", duration: 500});
1108
-        resizeLarge();
1109
-    };
1110
-
1111
-    if (chatspace.css("display") == 'block') {
1112
-        videospace.animate({right: 0}, {queue: false, duration: 500, progress: onHide});
1113
-    }
1114
-    else {
1115
-        videospace.animate({right: chatspace.width()},
1116
-                           {queue: false,
1117
-                            duration: 500,
1118
-                            progress: onShow,
1119
-                            complete: function() {
1120
-                                scrollChatToBottom();
1121
-                            }
1122
-                           });
1123
-    }
1124
-
1125
-    // Request the focus in the nickname field or the chat input field.
1126
-    if ($('#nickname').css('visibility') == 'visible')
1127
-        $('#nickinput').focus();
1128
-    else {
1129
-        $('#usermsg').focus();
1130
-    }
1131
-}
1132
-
1133 1018
 /*
1134 1019
  * Shows the call main toolbar.
1135 1020
  */
@@ -1199,7 +1084,7 @@ function addRemoteVideoContainer(id) {
1199 1084
     return container;
1200 1085
 }
1201 1086
 
1202
-/*
1087
+/**
1203 1088
  * Creates the element indicating the focus of the conference.
1204 1089
  */
1205 1090
 function createFocusIndicatorElement(parentElement) {
@@ -1209,13 +1094,7 @@ function createFocusIndicatorElement(parentElement) {
1209 1094
     parentElement.appendChild(focusIndicator);
1210 1095
 }
1211 1096
 
1212
-function scrollChatToBottom() {
1213
-    setTimeout(function() {
1214
-        $('#chatconversation').scrollTop($('#chatconversation')[0].scrollHeight);
1215
-    }, 5);
1216
-}
1217
-
1218
-/*
1097
+/**
1219 1098
  * Toggles the application in and out of full screen mode 
1220 1099
  * (a.k.a. presentation mode in Chrome).
1221 1100
  */
@@ -1246,7 +1125,7 @@ function toggleFullScreen() {
1246 1125
 }
1247 1126
 
1248 1127
 /**
1249
- *
1128
+ * Shows the display name for the given video.
1250 1129
  */
1251 1130
 function showDisplayName(videoSpanId, displayName) {
1252 1131
     var nameSpan = $('#' + videoSpanId + '>span.displayname');
@@ -1306,7 +1185,7 @@ function showDisplayName(videoSpanId, displayName) {
1306 1185
                         connection.emuc.addDisplayNameToPresence(nickname);
1307 1186
                         connection.emuc.sendPresence();
1308 1187
 
1309
-                        setChatConversationMode(true);
1188
+                        Chat.setChatConversationMode(true);
1310 1189
                     }
1311 1190
 
1312 1191
                     if (!$('#localDisplayName').is(":visible")) {
@@ -1337,13 +1216,4 @@ function createEditDisplayNameButton() {
1337 1216
     editButton.innerHTML = '<i class="fa fa-pencil"></i>';
1338 1217
 
1339 1218
     return editButton;
1340
-}
1341
-
1342
-function setChatConversationMode(isConversationMode) {
1343
-    if (isConversationMode) {
1344
-        $('#nickname').css({visibility:"hidden"});
1345
-        $('#chatconversation').css({visibility:'visible'});
1346
-        $('#usermsg').css({visibility:'visible'});
1347
-        $('#usermsg').focus();
1348
-    }
1349
-}
1219
+}

+ 222
- 0
chat.js View File

@@ -0,0 +1,222 @@
1
+/**
2
+ * Chat related user interface.
3
+ */
4
+var Chat = (function (my) {
5
+    var notificationInterval = false;
6
+    var unreadMessages = 0;
7
+
8
+    /**
9
+     * Initializes chat related interface.
10
+     */
11
+    my.init = function () {
12
+        var storedDisplayName = window.localStorage.displayname;
13
+        if (storedDisplayName) {
14
+            nickname = storedDisplayName;
15
+
16
+            Chat.setChatConversationMode(true);
17
+        }
18
+
19
+        $('#nickinput').keydown(function(event) {
20
+            if (event.keyCode == 13) {
21
+                event.preventDefault();
22
+                var val = this.value;
23
+                this.value = '';
24
+                if (!nickname) {
25
+                    nickname = val;
26
+                    window.localStorage.displayname = nickname;
27
+
28
+                    connection.emuc.addDisplayNameToPresence(nickname);
29
+                    connection.emuc.sendPresence();
30
+
31
+                    Chat.setChatConversationMode(true);
32
+
33
+                    return;
34
+                }
35
+            }
36
+        });
37
+
38
+        $('#usermsg').keydown(function(event) {
39
+            if (event.keyCode == 13) {
40
+                event.preventDefault();
41
+                var message = this.value;
42
+                $('#usermsg').val('').trigger('autosize.resize');
43
+                this.focus();
44
+                connection.emuc.sendMessage(message, nickname);
45
+            }
46
+        });
47
+
48
+        var onTextAreaResize = function() {
49
+            resizeChatConversation();
50
+            scrollChatToBottom();
51
+        };
52
+        $('#usermsg').autosize({callback: onTextAreaResize});
53
+
54
+        $("#chatspace").bind("shown",
55
+            function() {
56
+                unreadMessages = 0;
57
+                setVisualNotification(false);
58
+            });
59
+    };
60
+
61
+    /**
62
+     * Appends the given message to the chat conversation.
63
+     */
64
+    my.updateChatConversation = function (nick, message) {
65
+        var divClassName = '';
66
+
67
+        if (nickname == nick) {
68
+            divClassName = "localuser";
69
+        }
70
+        else {
71
+            divClassName = "remoteuser";
72
+
73
+            if (!$('#chatspace').is(":visible")) {
74
+                unreadMessages++;
75
+                Util.playSoundNotification('chatNotification');
76
+                setVisualNotification(true);
77
+            }
78
+        }
79
+
80
+        //replace links and smileys
81
+        message = processReplacements(message);
82
+
83
+        $('#chatconversation').append('<div class="' + divClassName + '"><b>'
84
+                                        + nick + ': </b>' + message + '</div>');
85
+        $('#chatconversation').animate(
86
+                { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
87
+    };
88
+
89
+    /**
90
+     * Opens / closes the chat area.
91
+     */
92
+    my.toggleChat = function () {
93
+        var chatspace = $('#chatspace');
94
+        var videospace = $('#videospace');
95
+
96
+        var onShow = function () {
97
+            resizeLarge();
98
+            $('#chatspace').show("slide", { direction: "right", duration: 500});
99
+        };
100
+        var onHide = function () {
101
+            $('#chatspace').hide("slide", { direction: "right", duration: 500});
102
+            resizeLarge();
103
+        };
104
+
105
+        if (chatspace.is(":visible")) {
106
+            videospace.animate( {right: 0},
107
+                                {queue: false,
108
+                                duration: 500,
109
+                                progress: onHide});
110
+        }
111
+        else {
112
+            videospace.animate({right: chatspace.width()},
113
+                               {queue: false,
114
+                                duration: 500,
115
+                                progress: onShow,
116
+                                complete: function() {
117
+                                    scrollChatToBottom();
118
+                                    chatspace.trigger('shown');
119
+                                }
120
+                               });
121
+        }
122
+
123
+        // Request the focus in the nickname field or the chat input field.
124
+        if ($('#nickname').css('visibility') == 'visible')
125
+            $('#nickinput').focus();
126
+        else {
127
+            $('#usermsg').focus();
128
+        }
129
+    };
130
+
131
+    /**
132
+     * Sets the chat conversation mode.
133
+     */
134
+    my.setChatConversationMode = function (isConversationMode) {
135
+        if (isConversationMode) {
136
+            $('#nickname').css({visibility:"hidden"});
137
+            $('#chatconversation').css({visibility:'visible'});
138
+            $('#usermsg').css({visibility:'visible'});
139
+            $('#usermsg').focus();
140
+        }
141
+    };
142
+
143
+    /**
144
+     * Resizes the chat area.
145
+     */
146
+    my.resizeChat = function () {
147
+        var availableHeight = window.innerHeight;
148
+        var availableWidth = window.innerWidth;
149
+
150
+        var chatWidth = 200;
151
+        if (availableWidth*0.2 < 200)
152
+            chatWidth = availableWidth*0.2;
153
+
154
+        $('#chatspace').width(chatWidth);
155
+        $('#chatspace').height(availableHeight - 40);
156
+
157
+        resizeChatConversation();
158
+    };
159
+
160
+    /**
161
+     * Resizes the chat conversation.
162
+     */
163
+    function resizeChatConversation() {
164
+        var usermsgStyleHeight = document.getElementById("usermsg").style.height;
165
+        var usermsgHeight = usermsgStyleHeight
166
+            .substring(0, usermsgStyleHeight.indexOf('px'));
167
+
168
+        $('#chatconversation').width($('#chatspace').width() - 10);
169
+        $('#chatconversation')
170
+            .height(window.innerHeight - 50 - parseInt(usermsgHeight));
171
+    };
172
+
173
+    /**
174
+     * Shows/hides a visual notification, indicating that a message has arrived.
175
+     */
176
+    function setVisualNotification(show) {
177
+        var unreadMsgElement = document.getElementById('unreadMessages');
178
+
179
+        if (unreadMessages) {
180
+            unreadMsgElement.innerHTML = unreadMessages.toString();
181
+
182
+            var chatButtonElement
183
+                = document.getElementById('chat').parentNode;
184
+            var leftIndent = (Util.getTextWidth(chatButtonElement)
185
+                                - Util.getTextWidth(unreadMsgElement) - 5)/2;
186
+            var topIndent = (Util.getTextHeight(chatButtonElement)
187
+                                - Util.getTextHeight(unreadMsgElement))/2 - 2;
188
+
189
+            unreadMsgElement.setAttribute(
190
+                    'style',
191
+                    'top:' + Util.toInteger(topIndent)
192
+                     + '; left:' + Util.toInteger(leftIndent) +';');
193
+        }
194
+        else
195
+            unreadMsgElement.innerHTML = '';
196
+
197
+        var glower = $('#chat');
198
+
199
+        if (show && !notificationInterval) {
200
+            notificationInterval = window.setInterval(function() {
201
+                glower.toggleClass('active');
202
+            }, 800);
203
+        }
204
+        else if (!show && notificationInterval) {
205
+            window.clearInterval(notificationInterval);
206
+            notificationInterval = false;
207
+            glower.removeClass('active');
208
+        }
209
+    }
210
+
211
+    /**
212
+     * Scrolls chat to the bottom.
213
+     */
214
+    function scrollChatToBottom() {
215
+        setTimeout(function() {
216
+            $('#chatconversation').scrollTop(
217
+                    $('#chatconversation')[0].scrollHeight);
218
+        }, 5);
219
+    }
220
+
221
+    return my;
222
+}(Chat || {}));

+ 42
- 13
css/main.css View File

@@ -3,7 +3,7 @@ html, body{
3 3
     height:100%;
4 4
     color: #424242;
5 5
     font-family:'Helvetica Neue', Helvetica, sans-serif;
6
-	font-weight: 400;
6
+    font-weight: 400;
7 7
     background: #e9e9e9;
8 8
     overflow-x: hidden;
9 9
 }
@@ -185,16 +185,16 @@ html, body{
185 185
 }
186 186
 
187 187
 #left {
188
-	display:block;
188
+    display:block;
189 189
     position: absolute;
190
-	left: 0px;
190
+    left: 0px;
191 191
     top: 0px;
192 192
     width: 100px;
193 193
     height: 39px;
194
-	background-image:url(../images/left1.png);
195
-	background-repeat:no-repeat;
196
-	margin: 0;
197
-	padding: 0;
194
+    background-image:url(../images/left1.png);
195
+    background-repeat:no-repeat;
196
+    margin: 0;
197
+    padding: 0;
198 198
 }
199 199
 
200 200
 #leftlogo {
@@ -222,6 +222,11 @@ html, body{
222 222
     visibility: hidden;
223 223
 }
224 224
 
225
+.toolbar_span {
226
+    display: inline-block;
227
+    position: relative;
228
+}
229
+
225 230
 .button {
226 231
     display: inline-block;
227 232
     position: relative;
@@ -233,6 +238,30 @@ html, body{
233 238
     font-size: 11pt;
234 239
     text-align: center;
235 240
     text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.7);
241
+    z-index: 1;
242
+}
243
+
244
+.toolbar_span>span {
245
+    display: inline-block;
246
+    position: absolute;
247
+    font-size: 7pt;
248
+    color: #ffffff;
249
+    text-align:center;
250
+    cursor: pointer;
251
+}
252
+
253
+#chat {
254
+    font-size:1.65em;
255
+    -webkit-transition: all .5s ease-in-out;;
256
+       -moz-transition: all .5s ease-in-out;;
257
+            transition: all .5s ease-in-out;;
258
+}
259
+
260
+#chat.active {
261
+    -webkit-text-shadow: 0 0 10px #ffffff;
262
+    -moz-text-shadow: 0 0 10px #ffffff;
263
+    text-shadow: 0 0 10px #ffffff;
264
+    -webkit-transform: scale(1.1);
236 265
 }
237 266
 
238 267
 a.button:hover {
@@ -266,15 +295,15 @@ a.button:hover {
266 295
 }
267 296
 
268 297
 #right {
269
-	display:block;
298
+    display:block;
270 299
     position:absolute;
271 300
     right: 0px;
272 301
     top: 0px;
273
-	background-image:url(../images/right1.png);
274
-	background-repeat:no-repeat;
275
-	margin:0;
276
-	padding:0;
277
-	width:100px;
302
+    background-image:url(../images/right1.png);
303
+    background-repeat:no-repeat;
304
+    margin:0;
305
+    padding:0;
306
+    width:100px;
278 307
     height:39px;
279 308
 }
280 309
 

+ 4
- 2
etherpad.js View File

@@ -15,7 +15,8 @@ var Etherpad = (function (my) {
15 15
 
16 16
             if (!name) {
17 17
                 // In case we're the focus we generate the name.
18
-                etherpadName = Math.random().toString(36).substring(7) + '_' + (new Date().getTime()).toString();
18
+                etherpadName = Math.random().toString(36).substring(7)
19
+                                + '_' + (new Date().getTime()).toString();
19 20
                 shareEtherpad();
20 21
             }
21 22
             else
@@ -94,7 +95,8 @@ var Etherpad = (function (my) {
94 95
         button.appendChild(buttonImage);
95 96
 
96 97
         var toolbar = document.getElementById('toolbar');
97
-        toolbar.insertBefore(button, toolbar.childNodes[toolbar.childNodes.length - 4]);
98
+        toolbar.insertBefore(button,
99
+                toolbar.childNodes[toolbar.childNodes.length - 4]);
98 100
         toolbar.insertBefore(separator, button);
99 101
     }
100 102
 

+ 15
- 5
index.html View File

@@ -8,6 +8,8 @@
8 8
     <script src="muc.js?v=6"></script><!-- simple MUC library -->
9 9
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
10 10
     <script src="app.js?v=20"></script><!-- application logic -->
11
+    <script src="chat.js?v=1"></script><!-- chat logic -->
12
+    <script src="util.js?v=1"></script><!-- utility functions -->
11 13
     <script src="etherpad.js?v=2"></script><!-- etherpad plugin -->
12 14
     <script src="smileys.js?v=1"></script><!-- smiley images -->
13 15
     <script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
@@ -25,17 +27,22 @@
25 27
         <a href="http://jitsi.org" target="_blank"><div id="leftlogo"></div></a>
26 28
         <a href="http://www.estos.com/" target="_blank"><div id="rightlogo"></div></a>
27 29
         <span id="toolbar">
28
-            <a class="button" onclick='buttonClick("#mute", "fa fa-microphone fa-lg fa fa-microphone-slash fa-lg");toggleAudio();'><i id="mute" title="Mute / unmute" class="fa fa-microphone fa-lg"></i></a>
30
+            <a class="button" onclick='buttonClick("#mute", "fa fa-microphone fa-lg fa fa-microphone-slash fa-lg");toggleAudio();'>
31
+                <i id="mute" title="Mute / unmute" class="fa fa-microphone fa-lg"></i></a>
29 32
             <div class="header_button_separator"></div>
30
-            <a class="button" onclick='buttonClick("#video", "fa fa-video-camera fa-lg fa fa-video-camera no-fa-video-camera fa-lg");toggleVideo();'><i id="video" title="Start / stop camera" class="fa fa-video-camera fa-lg"></i></a>
33
+            <a class="button" onclick='buttonClick("#video", "fa fa-video-camera fa-lg fa fa-video-camera no-fa-video-camera fa-lg");toggleVideo();'>
34
+                <i id="video" title="Start / stop camera" class="fa fa-video-camera fa-lg"></i></a>
31 35
             <div class="header_button_separator"></div>
32 36
             <a class="button" onclick="openLockDialog();"><i id="lockIcon" title="Lock/unlock room" class="fa fa-unlock fa-lg"></i></a>
33 37
             <div class="header_button_separator"></div>
34 38
             <a class="button" onclick="openLinkDialog();"><i title="Invite others" class="fa fa-link fa-lg"></i></a>
35 39
             <div class="header_button_separator"></div>
36
-            <a class="button" onclick='openChat();'><i id="chat" title="Open chat" class="fa fa-comments fa-lg"></i></a>
40
+            <span class="toolbar_span">
41
+                <a class="button" onclick='Chat.toggleChat();'><i id="chat" title="Open chat" class="fa fa-comments-o fa-lg"></i></a>
42
+                <span id="unreadMessages"></span>
43
+            </span>
37 44
             <div class="header_button_separator"></div>
38
-            <a class="button" onclick='openPreziDialog();'><i title="Share prezi" class="fa fa-desktop fa-lg"></i></a>
45
+            <a class="button" onclick='openPreziDialog();'><i title="Share prezi" class="fa fa-picture-o fa-lg"></i></a>
39 46
             <div class="header_button_separator"></div>
40 47
             <a class="button" onclick='toggleFullScreen();'><i title="Enter / Exit Full Screen" class="fa fa-arrows-alt fa-lg"></i></a>
41 48
         </span>
@@ -65,6 +72,8 @@
65 72
                 <video id="localVideo" autoplay oncontextmenu="return false;" muted></video>
66 73
                 <span class="focusindicator"></span>
67 74
             </span>
75
+            <audio id="userJoined" src="sounds/joined.wav" preload="auto"></audio>
76
+            <audio id="userLeft" src="sounds/left.wav" preload="auto"></audio>
68 77
         </div>
69 78
     </div>
70 79
     <div id="chatspace">
@@ -74,9 +83,10 @@
74 83
                 <input type='text' id="nickinput" placeholder='Choose a nickname' autofocus>
75 84
             </form>
76 85
         </div>
77
-        
86
+
78 87
         <!--div><i class="fa fa-comments">&nbsp;</i><span class='nick'></span>:&nbsp;<span class='chattext'></span></div-->
79 88
         <div id="chatconversation"></div>
89
+        <audio id="chatNotification" src="sounds/incomingMessage.wav" preload="auto"></audio>
80 90
         <textarea id="usermsg" placeholder='Enter text...' autofocus></textarea>
81 91
     </div>
82 92
     <a id="downloadlog" onclick='dump(event.target);'><i title="Download support information" class="fa fa-cloud-download"></i></a>

+ 1
- 1
muc.js View File

@@ -143,7 +143,7 @@ Strophe.addConnectionPlugin('emuc', {
143 143
         if (txt) {
144 144
             console.log('chat', nick, txt);
145 145
 
146
-            updateChatConversation(nick, txt);
146
+            Chat.updateChatConversation(nick, txt);
147 147
         }
148 148
         return true;
149 149
     },

BIN
sounds/incomingMessage.wav View File


BIN
sounds/joined.wav View File


BIN
sounds/left.wav View File


+ 43
- 0
util.js View File

@@ -0,0 +1,43 @@
1
+/**
2
+ * Utility functions.
3
+ */
4
+var Util = (function (my) {
5
+
6
+    /**
7
+     * Returns the text width for the given element.
8
+     *
9
+     * @param el the element
10
+     */
11
+    my.getTextWidth = function(el) {
12
+        return (el.clientWidth + 1);
13
+    };
14
+
15
+    /**
16
+     * Returns the text height for the given element.
17
+     *
18
+     * @param el the element
19
+     */
20
+    my.getTextHeight = function(el) {
21
+        return (el.clientHeight + 1);
22
+    };
23
+
24
+    /**
25
+     * Casts the given number to integer.
26
+     *
27
+     * @param number the number to cast
28
+     */
29
+    my.toInteger = function(number) {
30
+        return Math.round(Number(number));
31
+    };
32
+
33
+    /**
34
+     * Plays the sound given by id.
35
+     *
36
+     * @param id the identifier of the audio element.
37
+     */
38
+    my.playSoundNotification = function(id) {
39
+        document.getElementById(id).play();
40
+    };
41
+
42
+    return my;
43
+}(Util || {}));

Loading…
Cancel
Save