Pārlūkot izejas kodu

Adds support for etherpad in meet.jit.si. Issue #36.

master
Yana Stamcheva 11 gadus atpakaļ
vecāks
revīzija
4ff1f4a30e
5 mainītis faili ar 188 papildinājumiem un 19 dzēšanām
  1. 28
    8
      app.js
  2. 3
    3
      css/main.css
  3. 136
    0
      etherpad.js
  4. 6
    8
      index.html
  5. 15
    0
      muc.js

+ 28
- 8
app.js Parādīt failu

86
             window.history.pushState('VideoChat', 'Room: ' + roomnode, window.location.pathname + roomnode);
86
             window.history.pushState('VideoChat', 'Room: ' + roomnode, window.location.pathname + roomnode);
87
         }
87
         }
88
     }
88
     }
89
+
89
     roomjid = roomnode + '@' + config.hosts.muc;
90
     roomjid = roomnode + '@' + config.hosts.muc;
90
 
91
 
91
     if (config.useNicks) {
92
     if (config.useNicks) {
111
     updateLargeVideo(localVideoSrc, true, 0);
112
     updateLargeVideo(localVideoSrc, true, 0);
112
 
113
 
113
     $('#localVideo').click(function () {
114
     $('#localVideo').click(function () {
114
-	updateLargeVideo($(this).attr('src'), true, 0);
115
+        $(document).trigger("video.selected", [false]);
116
+        updateLargeVideo($(this).attr('src'), true, 0);
117
+
115
         $('video').each(function (idx, el) {
118
         $('video').each(function (idx, el) {
116
             if (el.id.indexOf('mixedmslabel') != -1) {
119
             if (el.id.indexOf('mixedmslabel') != -1) {
117
                 el.volume = 0;
120
                 el.volume = 0;
217
     };
220
     };
218
     sel.click(
221
     sel.click(
219
         function () {
222
         function () {
223
+            $(document).trigger("video.selected", [false]);
220
             updateLargeVideo($(this).attr('src'), false, 1);
224
             updateLargeVideo($(this).attr('src'), false, 1);
221
         }
225
         }
222
     );
226
     );
282
         focus = new ColibriFocus(connection, config.hosts.bridge);
286
         focus = new ColibriFocus(connection, config.hosts.bridge);
283
     }
287
     }
284
 
288
 
289
+    if (focus && config.etherpad_base) {
290
+        Etherpad.init();
291
+    }
292
+
285
     showFocusIndicator();
293
     showFocusIndicator();
286
 
294
 
287
     // Once we've joined the muc show the toolbar
295
     // Once we've joined the muc show the toolbar
338
         $(container).hide();
346
         $(container).hide();
339
         resizeThumbnails();
347
         resizeThumbnails();
340
     }
348
     }
341
-
342
     if (focus === null && connection.emuc.myroomjid == connection.emuc.list_members[0]) {
349
     if (focus === null && connection.emuc.myroomjid == connection.emuc.list_members[0]) {
343
         console.log('welcome to our new focus... myself');
350
         console.log('welcome to our new focus... myself');
344
         focus = new ColibriFocus(connection, config.hosts.bridge);
351
         focus = new ColibriFocus(connection, config.hosts.bridge);
345
         if (Object.keys(connection.emuc.members).length > 0) {
352
         if (Object.keys(connection.emuc.members).length > 0) {
346
             focus.makeConference(Object.keys(connection.emuc.members));
353
             focus.makeConference(Object.keys(connection.emuc.members));
347
         }
354
         }
355
+        $(document).trigger('focusechanged.muc', [focus]);
348
     } 
356
     } 
349
     else if (focus && Object.keys(connection.emuc.members).length === 0) {
357
     else if (focus && Object.keys(connection.emuc.members).length === 0) {
350
         console.log('everyone left');
358
         console.log('everyone left');
437
     setPresentationVisible(true);
445
     setPresentationVisible(true);
438
     $('#largeVideoContainer').hover(
446
     $('#largeVideoContainer').hover(
439
         function (event) {
447
         function (event) {
440
-            if ($('#largeVideo').css('visibility') == 'hidden')
448
+            if (isPresentationVisible())
441
                 $('#reloadPresentation').css({display:'inline-block'});
449
                 $('#reloadPresentation').css({display:'inline-block'});
442
         },
450
         },
443
         function (event) {
451
         function (event) {
444
-            if ($('#largeVideo').css('visibility') == 'visible')
452
+            if (!isPresentationVisible())
445
                 $('#reloadPresentation').css({display:'none'});
453
                 $('#reloadPresentation').css({display:'none'});
446
             else {
454
             else {
447
                 var e = event.toElement || event.relatedTarget;
455
                 var e = event.toElement || event.relatedTarget;
519
  */
527
  */
520
 function setPresentationVisible(visible) {
528
 function setPresentationVisible(visible) {
521
     if (visible) {
529
     if (visible) {
530
+        // Trigger the video.selected event to indicate a change in the large video.
531
+        $(document).trigger("video.selected", [true]);
532
+
522
         $('#largeVideo').fadeOut(300, function () {
533
         $('#largeVideo').fadeOut(300, function () {
523
             $('#largeVideo').css({visibility:'hidden'});
534
             $('#largeVideo').css({visibility:'hidden'});
524
             $('#presentation>iframe').fadeIn(300, function() {
535
             $('#presentation>iframe').fadeIn(300, function() {
538
     }
549
     }
539
 }
550
 }
540
 
551
 
552
+var isPresentationVisible = function () {
553
+    return ($('#presentation>iframe') != null && $('#presentation>iframe').css('opacity') == 1);
554
+}
555
+
541
 /**
556
 /**
542
  * Updates the large video with the given new video source.
557
  * Updates the large video with the given new video source.
543
  */
558
  */
607
         $('#presentation>iframe').width(availableWidth);
622
         $('#presentation>iframe').width(availableWidth);
608
         $('#presentation>iframe').height(availableWidth / aspectRatio);
623
         $('#presentation>iframe').height(availableWidth / aspectRatio);
609
     }
624
     }
610
-    
625
+
626
+    if ($('#etherpad>iframe')) {
627
+        $('#etherpad>iframe').width(availableWidth);
628
+        $('#etherpad>iframe').height(availableWidth / aspectRatio);
629
+    }
630
+
611
     resizeThumbnails();
631
     resizeThumbnails();
612
 }
632
 }
613
 
633
 
614
 function resizeThumbnails() {
634
 function resizeThumbnails() {
615
     // Calculate the available height, which is the inner window height minus 39px for the header
635
     // Calculate the available height, which is the inner window height minus 39px for the header
616
-    // minus 4px for the delimiter lines on the top and bottom of the large video,
636
+    // minus 2px for the delimiter lines on the top and bottom of the large video,
617
     // minus the 36px space inside the remoteVideos container used for highlighting shadow.
637
     // minus the 36px space inside the remoteVideos container used for highlighting shadow.
618
-    var availableHeight = window.innerHeight - $('#largeVideo').height() - 79;
638
+    var availableHeight = window.innerHeight - $('#largeVideo').height() - 59;
619
     var numvids = $('#remoteVideos>span:visible').length;
639
     var numvids = $('#remoteVideos>span:visible').length;
620
 
640
 
621
     // Remove the 1px borders arround videos and the chat width.
641
     // Remove the 1px borders arround videos and the chat width.
629
     }
649
     }
630
 
650
 
631
     // size videos so that while keeping AR and max height, we have a nice fit
651
     // size videos so that while keeping AR and max height, we have a nice fit
632
-    $('#remoteVideos').height(availableHeight+26); // add the 2*18px-padding-top border used for highlighting shadow.
652
+    $('#remoteVideos').height(availableHeight);
633
     $('#remoteVideos>span').width(availableWidth);
653
     $('#remoteVideos>span').width(availableWidth);
634
     $('#remoteVideos>span').height(availableHeight);
654
     $('#remoteVideos>span').height(availableHeight);
635
 }
655
 }

+ 3
- 3
css/main.css Parādīt failu

22
     margin-left: auto;
22
     margin-left: auto;
23
     margin-right: auto;
23
     margin-right: auto;
24
 }
24
 }
25
-#presentation, .videocontainer>video {
25
+#presentation, #etherpad, .videocontainer>video {
26
     position: absolute;
26
     position: absolute;
27
     left: 0px;
27
     left: 0px;
28
     top: 0px;
28
     top: 0px;
53
     position:relative;
53
     position:relative;
54
     text-align:center;
54
     text-align:center;
55
     height:196px;
55
     height:196px;
56
-    padding-top:10px;
56
+    padding: 5px 0px;
57
     width:auto;
57
     width:auto;
58
     overflow: hidden;
58
     overflow: hidden;
59
     border:1px solid transparent;
59
     border:1px solid transparent;
415
     background-clip: padding-box;
415
     background-clip: padding-box;
416
     -webkit-border-radius: 5px;
416
     -webkit-border-radius: 5px;
417
     -webkit-background-clip: padding-box;
417
     -webkit-background-clip: padding-box;
418
-    z-index: 2;
418
+    z-index: 3;
419
 }
419
 }

+ 136
- 0
etherpad.js Parādīt failu

1
+var Etherpad = (function (my) {
2
+    var etherpadName = null;
3
+
4
+    /**
5
+     * Initializes the etherpad.
6
+     */
7
+    my.init = function (name) {
8
+
9
+        if (config.etherpad_base && !etherpadName) {
10
+
11
+            if (!name) {
12
+                // In case we're the focus we generate the name.
13
+                etherpadName = Math.random().toString(36).substring(7) + '_' + (new Date().getTime()).toString();
14
+                shareEtherpad();
15
+            }
16
+            else
17
+                etherpadName = name;
18
+                
19
+            this.domain = config.etherpad_base;
20
+            this.options = "?showControls=true&showChat=false&showLineNumbers=true&useMonospaceFont=false";
21
+
22
+            createEtherpadButton();
23
+
24
+            this.iframe = document.createElement('iframe');
25
+            this.iframe.src = this.domain + etherpadName + this.options;
26
+            this.iframe.frameBorder = 0;
27
+            this.iframe.scrolling = "no";
28
+            this.iframe.width = $('#largeVideoContainer').width() || 640;
29
+            this.iframe.height = $('#largeVideoContainer').height() || 480;
30
+            this.iframe.setAttribute('style', 'visibility: hidden;');
31
+
32
+            document.getElementById('etherpad').appendChild(this.iframe);
33
+        }
34
+    }
35
+
36
+    /**
37
+     * Opens/hides the Etherpad.
38
+     */
39
+    my.toggleEtherpad = function (isPresentation) {
40
+        var largeVideo = null;
41
+        if (isPresentationVisible())
42
+            largeVideo = $('#presentation>iframe');
43
+        else
44
+            largeVideo = $('#largeVideo');
45
+
46
+        if ($('#etherpad>iframe').css('visibility') == 'hidden') {
47
+            largeVideo.fadeOut(300, function () {
48
+                if (isPresentationVisible())
49
+                    largeVideo.css({opacity:'0'});
50
+                else
51
+                    largeVideo.css({visibility:'hidden'});
52
+
53
+                $('#etherpad>iframe').fadeIn(300, function() {
54
+                    $('#etherpad>iframe').css({visibility:'visible'});
55
+                    $('#etherpad').css({zIndex:2});
56
+                });
57
+            });
58
+        }
59
+        else if ($('#etherpad>iframe')) {
60
+            $('#etherpad>iframe').fadeOut(300, function () {
61
+                $('#etherpad>iframe').css({visibility:'hidden'});
62
+                $('#etherpad').css({zIndex:0});
63
+                if (!isPresentation) {
64
+                    $('#largeVideo').fadeIn(300, function() {
65
+                        $('#largeVideo').css({visibility:'visible'});
66
+                    });
67
+                }
68
+            });
69
+        }
70
+    };
71
+
72
+    /**
73
+     * Shares the Etherpad name with other participants.
74
+     */
75
+    function shareEtherpad() {
76
+        connection.emuc.addEtherpadToPresence(etherpadName);
77
+        connection.emuc.sendPresence();
78
+    }
79
+
80
+    /**
81
+     * Creates the Etherpad button and adds it to the toolbar.
82
+     */
83
+    function createEtherpadButton() {
84
+        //<div class="header_button_separator"></div>
85
+        //<a class="button" onclick='Etherpad.openEtherpad("teeest");'>
86
+        //<i title="Open shared document" class="fa fa-file-text fa-lg"></i></a>
87
+        var separator = document.createElement('div');
88
+        separator.className = 'header_button_separator';
89
+
90
+        var button = document.createElement('a');
91
+        button.className = 'button';
92
+        button.setAttribute('onclick', 'Etherpad.toggleEtherpad(0);');
93
+        
94
+        var buttonImage = document.createElement('i');
95
+        buttonImage.setAttribute('title', 'Open shared document');
96
+        buttonImage.className = 'fa fa-file-text fa-lg';
97
+
98
+        button.appendChild(buttonImage);
99
+
100
+        var toolbar = document.getElementById('toolbar');
101
+        toolbar.insertBefore(button, toolbar.childNodes[toolbar.childNodes.length - 4]);
102
+        toolbar.insertBefore(separator, button);
103
+    }
104
+
105
+    /**
106
+     * On Etherpad added to muc.
107
+     */
108
+    $(document).bind('etherpadadded.muc', function (event, jid, etherpadName) {
109
+        console.log("Etherpad added", etherpadName);
110
+        if (config.etherpad_base && !focus) {
111
+            Etherpad.init(etherpadName);
112
+        }
113
+    });
114
+
115
+    /**
116
+     * On focus changed event.
117
+     */
118
+    $(document).bind('focusechanged.muc', function (event, focus) {
119
+        console.log("Focus changed");
120
+        if (config.etherpad_base)
121
+            shareEtherpad();
122
+    });
123
+
124
+    /**
125
+     * On video selected event.
126
+     */
127
+    $(document).bind('video.selected', function (event, isPresentation) {
128
+        if (!config.etherpad_base)
129
+            return;
130
+
131
+        if ($('#etherpad>iframe').css('visibility') != 'hidden')
132
+            Etherpad.toggleEtherpad(isPresentation);
133
+    });
134
+
135
+    return my;
136
+}(Etherpad || {}));

+ 6
- 8
index.html Parādīt failu

5
     <script src="libs/strophejingle.bundle.js?v=7"></script><!-- strophe.jingle bundle -->
5
     <script src="libs/strophejingle.bundle.js?v=7"></script><!-- strophe.jingle bundle -->
6
     <script src="libs/colibri.js?v=7"></script><!-- colibri focus implementation -->
6
     <script src="libs/colibri.js?v=7"></script><!-- colibri focus implementation -->
7
     <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
7
     <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
8
-    <script src="muc.js?v=5"></script><!-- simple MUC library -->
8
+    <script src="muc.js?v=6"></script><!-- simple MUC library -->
9
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
9
     <script src="estos_log.js?v=2"></script><!-- simple stanza logger -->
10
-    <script src="app.js?v=19"></script><!-- application logic -->
10
+    <script src="app.js?v=20"></script><!-- application logic -->
11
+    <script src="etherpad.js?v=1"></script><!-- etherpad plugin -->
11
     <script src="smileys.js?v=1"></script><!-- smiley images -->
12
     <script src="smileys.js?v=1"></script><!-- smiley images -->
12
     <script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
13
     <script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
13
     <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
14
     <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
14
-    <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=15"/>
15
+    <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=16"/>
15
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
16
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
16
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
17
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
17
     <script src="libs/jquery-impromptu.js"></script>
18
     <script src="libs/jquery-impromptu.js"></script>
36
             <div class="header_button_separator"></div>
37
             <div class="header_button_separator"></div>
37
             <a class="button" onclick='openPreziDialog();'><i title="Share prezi" class="fa fa-desktop fa-lg"></i></a>
38
             <a class="button" onclick='openPreziDialog();'><i title="Share prezi" class="fa fa-desktop fa-lg"></i></a>
38
             <div class="header_button_separator"></div>
39
             <div class="header_button_separator"></div>
39
-            <a class="button" onclick='toggleFullScreen();'><i title="Enter / Exit Full Screen" class="fa fa-arrows-alt"></i></a>
40
-            <!--span id="settingsButton">
41
-                <div class="header_button_separator"></div>
42
-                <a class="button" onclick='openSettingsDialog();'><i title="Settings" class="fa fa-cog fa-lg"></i></a>
43
-            </span-->
40
+            <a class="button" onclick='toggleFullScreen();'><i title="Enter / Exit Full Screen" class="fa fa-arrows-alt fa-lg"></i></a>
44
         </span>
41
         </span>
45
     </div>
42
     </div>
46
     <div id="settings">
43
     <div id="settings">
58
         <div id="largeVideoContainer" class="videocontainer">
55
         <div id="largeVideoContainer" class="videocontainer">
59
             <div id="reloadPresentation"><a onclick='reloadPresentation();'><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
56
             <div id="reloadPresentation"><a onclick='reloadPresentation();'><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
60
             <div id="presentation"></div>
57
             <div id="presentation"></div>
58
+            <div id="etherpad"></div>
61
             <video id="largeVideo" autoplay oncontextmenu="return false;"></video>
59
             <video id="largeVideo" autoplay oncontextmenu="return false;"></video>
62
         </div>
60
         </div>
63
         <div class="fade_line"></div>
61
         <div class="fade_line"></div>

+ 15
- 0
muc.js Parādīt failu

43
             return true;
43
             return true;
44
         }
44
         }
45
 
45
 
46
+        // Parse etherpad tag.
47
+        var etherpad = $(pres).find('>etherpad');
48
+        if (etherpad.length) {
49
+            $(document).trigger('etherpadadded.muc', [from, etherpad.text()]);
50
+        }
51
+
52
+        // Parse prezi tag.
46
         var presentation = $(pres).find('>prezi');
53
         var presentation = $(pres).find('>prezi');
47
         if (presentation.length)
54
         if (presentation.length)
48
         {
55
         {
188
                             c('current').t(this.presMap['prezicurrent']).up().up();
195
                             c('current').t(this.presMap['prezicurrent']).up().up();
189
         }
196
         }
190
 
197
 
198
+        if (this.presMap['etherpadns']) {
199
+            pres.c('etherpad', {xmlns: this.presMap['etherpadns']}).t(this.presMap['etherpadname']).up();
200
+        }
201
+
191
         if (this.presMap['medians'])
202
         if (this.presMap['medians'])
192
         {
203
         {
193
             pres.c('media', {xmlns: this.presMap['medians']});
204
             pres.c('media', {xmlns: this.presMap['medians']});
232
     },
243
     },
233
     getPrezi: function (roomjid) {
244
     getPrezi: function (roomjid) {
234
         return this.preziMap[roomjid];
245
         return this.preziMap[roomjid];
246
+    },
247
+    addEtherpadToPresence: function(etherpadName) {
248
+        this.presMap['etherpadns'] = 'http://jitsi.org/jitmeet/etherpad';
249
+        this.presMap['etherpadname'] = etherpadName;
235
     }
250
     }
236
 });
251
 });

Notiek ielāde…
Atcelt
Saglabāt