|
@@ -27,17 +27,23 @@ var VideoLayout = (function (my) {
|
27
|
27
|
localVideoContainer.appendChild(localVideo);
|
28
|
28
|
|
29
|
29
|
var localVideoSelector = $('#' + localVideo.id);
|
30
|
|
- // Add click handler
|
|
30
|
+ // Add click handler to both video and video wrapper elements in case
|
|
31
|
+ // there's no video.
|
31
|
32
|
localVideoSelector.click(function () {
|
32
|
33
|
VideoLayout.handleVideoThumbClicked(localVideo.src);
|
33
|
34
|
});
|
|
35
|
+ $('#localVideoContainer').click(function () {
|
|
36
|
+ VideoLayout.handleVideoThumbClicked(localVideo.src);
|
|
37
|
+ });
|
|
38
|
+
|
34
|
39
|
// Add hover handler
|
35
|
40
|
$('#localVideoContainer').hover(
|
36
|
41
|
function() {
|
37
|
42
|
VideoLayout.showDisplayName('localVideoContainer', true);
|
38
|
43
|
},
|
39
|
44
|
function() {
|
40
|
|
- if (focusedVideoSrc !== localVideo.src)
|
|
45
|
+ if (!VideoLayout.isLargeVideoVisible()
|
|
46
|
+ || localVideo.src !== $('#largeVideo').attr('src'))
|
41
|
47
|
VideoLayout.showDisplayName('localVideoContainer', false);
|
42
|
48
|
}
|
43
|
49
|
);
|
|
@@ -103,6 +109,8 @@ var VideoLayout = (function (my) {
|
103
|
109
|
var isVisible = $('#largeVideo').is(':visible');
|
104
|
110
|
|
105
|
111
|
$('#largeVideo').fadeOut(300, function () {
|
|
112
|
+ var oldSrc = $(this).attr('src');
|
|
113
|
+
|
106
|
114
|
$(this).attr('src', newSrc);
|
107
|
115
|
|
108
|
116
|
// Screen stream is already rotated
|
|
@@ -129,8 +137,25 @@ var VideoLayout = (function (my) {
|
129
|
137
|
? getDesktopVideoPosition
|
130
|
138
|
: getCameraVideoPosition;
|
131
|
139
|
|
132
|
|
- if (isVisible)
|
|
140
|
+ if (isVisible) {
|
|
141
|
+ // Only if the large video is currently visible.
|
|
142
|
+ // Disable previous active speaker video.
|
|
143
|
+ var oldJid = getJidFromVideoSrc(oldSrc);
|
|
144
|
+ if (oldJid) {
|
|
145
|
+ var oldResourceJid = Strophe.getResourceFromJid(oldJid);
|
|
146
|
+ VideoLayout.enableActiveSpeaker(oldResourceJid, false);
|
|
147
|
+ }
|
|
148
|
+
|
|
149
|
+ // Enable new active speaker in the remote videos section.
|
|
150
|
+ var userJid = getJidFromVideoSrc(newSrc);
|
|
151
|
+ if (userJid)
|
|
152
|
+ {
|
|
153
|
+ var resourceJid = Strophe.getResourceFromJid(userJid);
|
|
154
|
+ VideoLayout.enableActiveSpeaker(resourceJid, true);
|
|
155
|
+ }
|
|
156
|
+
|
133
|
157
|
$(this).fadeIn(300);
|
|
158
|
+ }
|
134
|
159
|
});
|
135
|
160
|
}
|
136
|
161
|
};
|
|
@@ -142,8 +167,6 @@ var VideoLayout = (function (my) {
|
142
|
167
|
|
143
|
168
|
if (oldContainer) {
|
144
|
169
|
oldContainer.removeClass("videoContainerFocused");
|
145
|
|
- VideoLayout.enableActiveSpeaker(
|
146
|
|
- Strophe.getResourceFromJid(focusJid), false);
|
147
|
170
|
}
|
148
|
171
|
|
149
|
172
|
// Unlock current focused.
|
|
@@ -152,30 +175,29 @@ var VideoLayout = (function (my) {
|
152
|
175
|
focusedVideoSrc = null;
|
153
|
176
|
// Enable the currently set active speaker.
|
154
|
177
|
if (currentActiveSpeaker) {
|
155
|
|
- VideoLayout.enableActiveSpeaker(currentActiveSpeaker, true);
|
|
178
|
+ var activeSpeakerVideo = document
|
|
179
|
+ .getElementById('participant_' + currentActiveSpeaker);
|
|
180
|
+
|
|
181
|
+ if (activeSpeakerVideo)
|
|
182
|
+ VideoLayout.updateLargeVideo(activeSpeakerVideo.src, 1);
|
156
|
183
|
}
|
157
|
184
|
|
158
|
185
|
return;
|
159
|
186
|
}
|
160
|
|
- // Remove style for current active speaker if we're going to lock
|
161
|
|
- // another video.
|
162
|
|
- else if (currentActiveSpeaker) {
|
163
|
|
- VideoLayout.enableActiveSpeaker(currentActiveSpeaker, false);
|
164
|
|
- }
|
165
|
187
|
|
166
|
188
|
// Lock new video
|
167
|
189
|
focusedVideoSrc = videoSrc;
|
168
|
190
|
|
|
191
|
+ // Update focused/pinned interface.
|
169
|
192
|
var userJid = getJidFromVideoSrc(videoSrc);
|
170
|
193
|
if (userJid)
|
171
|
194
|
{
|
172
|
195
|
var container = getParticipantContainer(userJid);
|
173
|
196
|
container.addClass("videoContainerFocused");
|
174
|
|
-
|
175
|
|
- var resourceJid = Strophe.getResourceFromJid(userJid);
|
176
|
|
- VideoLayout.enableActiveSpeaker(resourceJid, true);
|
177
|
197
|
}
|
178
|
198
|
|
|
199
|
+ // Triggers a "video.selected" event. The "false" parameter indicates
|
|
200
|
+ // this isn't a prezi.
|
179
|
201
|
$(document).trigger("video.selected", [false]);
|
180
|
202
|
|
181
|
203
|
VideoLayout.updateLargeVideo(videoSrc, 1);
|
|
@@ -224,16 +246,29 @@ var VideoLayout = (function (my) {
|
224
|
246
|
* Shows/hides the large video.
|
225
|
247
|
*/
|
226
|
248
|
my.setLargeVideoVisible = function(isVisible) {
|
|
249
|
+ var largeVideoJid = getJidFromVideoSrc($('#largeVideo').attr('src'));
|
|
250
|
+ var resourceJid = Strophe.getResourceFromJid(largeVideoJid);
|
|
251
|
+
|
227
|
252
|
if (isVisible) {
|
228
|
253
|
$('#largeVideo').css({visibility: 'visible'});
|
229
|
254
|
$('.watermark').css({visibility: 'visible'});
|
|
255
|
+ VideoLayout.enableActiveSpeaker(resourceJid, true);
|
230
|
256
|
}
|
231
|
257
|
else {
|
232
|
258
|
$('#largeVideo').css({visibility: 'hidden'});
|
233
|
259
|
$('.watermark').css({visibility: 'hidden'});
|
|
260
|
+ VideoLayout.enableActiveSpeaker(resourceJid, false);
|
234
|
261
|
}
|
235
|
262
|
};
|
236
|
263
|
|
|
264
|
+ /**
|
|
265
|
+ * Indicates if the large video is currently visible.
|
|
266
|
+ *
|
|
267
|
+ * @return <tt>true</tt> if visible, <tt>false</tt> - otherwise
|
|
268
|
+ */
|
|
269
|
+ my.isLargeVideoVisible = function() {
|
|
270
|
+ return $('#largeVideo').is(':visible');
|
|
271
|
+ };
|
237
|
272
|
|
238
|
273
|
/**
|
239
|
274
|
* Checks if container for participant identified by given peerJid exists
|
|
@@ -284,6 +319,8 @@ var VideoLayout = (function (my) {
|
284
|
319
|
*/
|
285
|
320
|
my.setDisplayName = function(videoSpanId, displayName) {
|
286
|
321
|
var nameSpan = $('#' + videoSpanId + '>span.displayname');
|
|
322
|
+ var defaultLocalDisplayName = "Me";
|
|
323
|
+ var defaultRemoteDisplayName = "Speaker";
|
287
|
324
|
|
288
|
325
|
// If we already have a display name for this video.
|
289
|
326
|
if (nameSpan.length > 0) {
|
|
@@ -291,21 +328,33 @@ var VideoLayout = (function (my) {
|
291
|
328
|
|
292
|
329
|
if (nameSpanElement.id === 'localDisplayName' &&
|
293
|
330
|
$('#localDisplayName').text() !== displayName) {
|
294
|
|
- $('#localDisplayName').text(displayName);
|
|
331
|
+ if (displayName)
|
|
332
|
+ $('#localDisplayName').text(displayName + ' (me)');
|
|
333
|
+ else
|
|
334
|
+ $('#localDisplayName').text(defaultLocalDisplayName);
|
295
|
335
|
} else {
|
296
|
|
- $('#' + videoSpanId + '_name').text(displayName);
|
|
336
|
+ if (displayName)
|
|
337
|
+ $('#' + videoSpanId + '_name').text(displayName);
|
|
338
|
+ else
|
|
339
|
+ $('#' + videoSpanId + '_name').text(defaultRemoteDisplayName);
|
297
|
340
|
}
|
298
|
341
|
} else {
|
299
|
342
|
var editButton = null;
|
300
|
343
|
|
|
344
|
+ nameSpan = document.createElement('span');
|
|
345
|
+ nameSpan.className = 'displayname';
|
|
346
|
+ $('#' + videoSpanId)[0].appendChild(nameSpan);
|
|
347
|
+
|
301
|
348
|
if (videoSpanId === 'localVideoContainer') {
|
302
|
349
|
editButton = createEditDisplayNameButton();
|
|
350
|
+ nameSpan.innerText = defaultLocalDisplayName;
|
303
|
351
|
}
|
304
|
|
- if (displayName.length) {
|
305
|
|
- nameSpan = document.createElement('span');
|
306
|
|
- nameSpan.className = 'displayname';
|
|
352
|
+ else {
|
|
353
|
+ nameSpan.innerText = defaultRemoteDisplayName;
|
|
354
|
+ }
|
|
355
|
+
|
|
356
|
+ if (displayName && displayName.length) {
|
307
|
357
|
nameSpan.innerText = displayName;
|
308
|
|
- $('#' + videoSpanId)[0].appendChild(nameSpan);
|
309
|
358
|
}
|
310
|
359
|
|
311
|
360
|
if (!editButton) {
|
|
@@ -327,7 +376,9 @@ var VideoLayout = (function (my) {
|
327
|
376
|
editableText.setAttribute('placeholder', 'ex. Jane Pink');
|
328
|
377
|
$('#' + videoSpanId)[0].appendChild(editableText);
|
329
|
378
|
|
330
|
|
- $('#localVideoContainer .displayname').bind("click", function (e) {
|
|
379
|
+ $('#localVideoContainer .displayname')
|
|
380
|
+ .bind("click", function (e) {
|
|
381
|
+
|
331
|
382
|
e.preventDefault();
|
332
|
383
|
$('#localDisplayName').hide();
|
333
|
384
|
$('#editDisplayName').show();
|
|
@@ -345,16 +396,15 @@ var VideoLayout = (function (my) {
|
345
|
396
|
}
|
346
|
397
|
|
347
|
398
|
if (!$('#localDisplayName').is(":visible")) {
|
348
|
|
- if (nickname) {
|
|
399
|
+ if (nickname)
|
349
|
400
|
$('#localDisplayName').text(nickname + " (me)");
|
350
|
|
- $('#localDisplayName').show();
|
351
|
|
- }
|
352
|
|
- else {
|
353
|
|
- $('#localDisplayName').text(nickname);
|
354
|
|
- }
|
355
|
|
-
|
356
|
|
- $('#editDisplayName').hide();
|
|
401
|
+ else
|
|
402
|
+ $('#localDisplayName')
|
|
403
|
+ .text(defaultLocalDisplayName);
|
|
404
|
+ $('#localDisplayName').show();
|
357
|
405
|
}
|
|
406
|
+
|
|
407
|
+ $('#editDisplayName').hide();
|
358
|
408
|
};
|
359
|
409
|
|
360
|
410
|
$('#editDisplayName').one("focusout", function (e) {
|
|
@@ -378,8 +428,11 @@ var VideoLayout = (function (my) {
|
378
|
428
|
* @param isShow indicates if the display name should be shown or hidden
|
379
|
429
|
*/
|
380
|
430
|
my.showDisplayName = function(videoSpanId, isShow) {
|
381
|
|
- var nameSpan = $('#' + videoSpanId + '>span.displayname').get(0);
|
382
|
|
-
|
|
431
|
+ // FIX: need to use noConflict of jquery, because apparently we're
|
|
432
|
+ // using another library that uses $, which conflics with jquery and
|
|
433
|
+ // sometimes objects are null because of that!!!!!!!!!
|
|
434
|
+ // http://api.jquery.com/jQuery.noConflict/
|
|
435
|
+ var nameSpan = jQuery('#' + videoSpanId + '>span.displayname').get(0);
|
383
|
436
|
if (isShow) {
|
384
|
437
|
if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length)
|
385
|
438
|
nameSpan.setAttribute("style", "display:inline-block;");
|
|
@@ -540,16 +593,24 @@ var VideoLayout = (function (my) {
|
540
|
593
|
if (nameSpan.length > 0)
|
541
|
594
|
displayName = nameSpan.text();
|
542
|
595
|
|
543
|
|
- console.log("Enable active speaker", displayName, isEnable);
|
|
596
|
+ console.log("UI enable active speaker",
|
|
597
|
+ displayName,
|
|
598
|
+ resourceJid,
|
|
599
|
+ isEnable);
|
544
|
600
|
|
545
|
601
|
var videoSpanId = null;
|
|
602
|
+ var videoContainerId = null;
|
546
|
603
|
if (resourceJid
|
547
|
|
- === Strophe.getResourceFromJid(connection.emuc.myroomjid))
|
|
604
|
+ === Strophe.getResourceFromJid(connection.emuc.myroomjid)) {
|
548
|
605
|
videoSpanId = 'localVideoWrapper';
|
549
|
|
- else
|
|
606
|
+ videoContainerId = 'localVideoContainer';
|
|
607
|
+ }
|
|
608
|
+ else {
|
550
|
609
|
videoSpanId = 'participant_' + resourceJid;
|
|
610
|
+ videoContainerId = videoSpanId;
|
|
611
|
+ }
|
551
|
612
|
|
552
|
|
- videoSpan = document.getElementById(videoSpanId);
|
|
613
|
+ videoSpan = document.getElementById(videoContainerId);
|
553
|
614
|
|
554
|
615
|
if (!videoSpan) {
|
555
|
616
|
console.error("No video element for jid", resourceJid);
|
|
@@ -559,18 +620,21 @@ var VideoLayout = (function (my) {
|
559
|
620
|
var video = $('#' + videoSpanId + '>video');
|
560
|
621
|
|
561
|
622
|
if (video && video.length > 0) {
|
562
|
|
- var videoElement = video.get(0);
|
563
|
623
|
if (isEnable) {
|
564
|
|
- if (!videoElement.classList.contains("activespeaker"))
|
565
|
|
- videoElement.classList.add("activespeaker");
|
|
624
|
+ VideoLayout.showDisplayName(videoContainerId, true);
|
566
|
625
|
|
567
|
|
- VideoLayout.showDisplayName(videoSpanId, true);
|
|
626
|
+ if (!videoSpan.classList.contains("activespeaker"))
|
|
627
|
+ videoSpan.classList.add("activespeaker");
|
|
628
|
+
|
|
629
|
+ video.css({visibility: 'hidden'});
|
568
|
630
|
}
|
569
|
631
|
else {
|
570
|
|
- VideoLayout.showDisplayName(videoSpanId, false);
|
|
632
|
+ VideoLayout.showDisplayName(videoContainerId, false);
|
|
633
|
+
|
|
634
|
+ if (videoSpan.classList.contains("activespeaker"))
|
|
635
|
+ videoSpan.classList.remove("activespeaker");
|
571
|
636
|
|
572
|
|
- if (videoElement.classList.contains("activespeaker"))
|
573
|
|
- videoElement.classList.remove("activespeaker");
|
|
637
|
+ video.css({visibility: 'visible'});
|
574
|
638
|
}
|
575
|
639
|
}
|
576
|
640
|
};
|
|
@@ -733,10 +797,10 @@ var VideoLayout = (function (my) {
|
733
|
797
|
};
|
734
|
798
|
|
735
|
799
|
/**
|
736
|
|
- * Returns the current active speaker.
|
|
800
|
+ * Returns the current active speaker resource jid.
|
737
|
801
|
*/
|
738
|
|
- my.getActiveSpeakerContainerId = function () {
|
739
|
|
- return 'participant_' + currentActiveSpeaker;
|
|
802
|
+ my.getActiveSpeakerResourceJid = function () {
|
|
803
|
+ return currentActiveSpeaker;
|
740
|
804
|
};
|
741
|
805
|
|
742
|
806
|
/**
|
|
@@ -862,18 +926,6 @@ var VideoLayout = (function (my) {
|
862
|
926
|
=== Strophe.getResourceFromJid(connection.emuc.myroomjid))
|
863
|
927
|
return;
|
864
|
928
|
|
865
|
|
- // Disable style for previous active speaker.
|
866
|
|
- if (currentActiveSpeaker
|
867
|
|
- && currentActiveSpeaker !== resourceJid
|
868
|
|
- && !focusedVideoSrc) {
|
869
|
|
- var oldContainer = document.getElementById(
|
870
|
|
- 'participant_' + currentActiveSpeaker);
|
871
|
|
-
|
872
|
|
- if (oldContainer) {
|
873
|
|
- VideoLayout.enableActiveSpeaker(currentActiveSpeaker, false);
|
874
|
|
- }
|
875
|
|
- }
|
876
|
|
-
|
877
|
929
|
// Obtain container for new active speaker.
|
878
|
930
|
var container = document.getElementById(
|
879
|
931
|
'participant_' + resourceJid);
|
|
@@ -892,7 +944,6 @@ var VideoLayout = (function (my) {
|
892
|
944
|
if (video.length)
|
893
|
945
|
{
|
894
|
946
|
VideoLayout.updateLargeVideo(video[0].src);
|
895
|
|
- VideoLayout.enableActiveSpeaker(resourceJid, true);
|
896
|
947
|
}
|
897
|
948
|
}
|
898
|
949
|
});
|