瀏覽代碼

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

j8
Yana Stamcheva 11 年之前
父節點
當前提交
4ff1f4a30e
共有 5 個檔案被更改,包括 188 行新增19 行删除
  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 查看文件

@@ -86,6 +86,7 @@ function doJoin() {
86 86
             window.history.pushState('VideoChat', 'Room: ' + roomnode, window.location.pathname + roomnode);
87 87
         }
88 88
     }
89
+
89 90
     roomjid = roomnode + '@' + config.hosts.muc;
90 91
 
91 92
     if (config.useNicks) {
@@ -111,7 +112,9 @@ $(document).bind('mediaready.jingle', function (event, stream) {
111 112
     updateLargeVideo(localVideoSrc, true, 0);
112 113
 
113 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 118
         $('video').each(function (idx, el) {
116 119
             if (el.id.indexOf('mixedmslabel') != -1) {
117 120
                 el.volume = 0;
@@ -217,6 +220,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
217 220
     };
218 221
     sel.click(
219 222
         function () {
223
+            $(document).trigger("video.selected", [false]);
220 224
             updateLargeVideo($(this).attr('src'), false, 1);
221 225
         }
222 226
     );
@@ -282,6 +286,10 @@ $(document).bind('joined.muc', function (event, jid, info) {
282 286
         focus = new ColibriFocus(connection, config.hosts.bridge);
283 287
     }
284 288
 
289
+    if (focus && config.etherpad_base) {
290
+        Etherpad.init();
291
+    }
292
+
285 293
     showFocusIndicator();
286 294
 
287 295
     // Once we've joined the muc show the toolbar
@@ -338,13 +346,13 @@ $(document).bind('left.muc', function (event, jid) {
338 346
         $(container).hide();
339 347
         resizeThumbnails();
340 348
     }
341
-
342 349
     if (focus === null && connection.emuc.myroomjid == connection.emuc.list_members[0]) {
343 350
         console.log('welcome to our new focus... myself');
344 351
         focus = new ColibriFocus(connection, config.hosts.bridge);
345 352
         if (Object.keys(connection.emuc.members).length > 0) {
346 353
             focus.makeConference(Object.keys(connection.emuc.members));
347 354
         }
355
+        $(document).trigger('focusechanged.muc', [focus]);
348 356
     } 
349 357
     else if (focus && Object.keys(connection.emuc.members).length === 0) {
350 358
         console.log('everyone left');
@@ -437,11 +445,11 @@ $(document).bind('presentationadded.muc', function (event, jid, presUrl, current
437 445
     setPresentationVisible(true);
438 446
     $('#largeVideoContainer').hover(
439 447
         function (event) {
440
-            if ($('#largeVideo').css('visibility') == 'hidden')
448
+            if (isPresentationVisible())
441 449
                 $('#reloadPresentation').css({display:'inline-block'});
442 450
         },
443 451
         function (event) {
444
-            if ($('#largeVideo').css('visibility') == 'visible')
452
+            if (!isPresentationVisible())
445 453
                 $('#reloadPresentation').css({display:'none'});
446 454
             else {
447 455
                 var e = event.toElement || event.relatedTarget;
@@ -519,6 +527,9 @@ function reloadPresentation() {
519 527
  */
520 528
 function setPresentationVisible(visible) {
521 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 533
         $('#largeVideo').fadeOut(300, function () {
523 534
             $('#largeVideo').css({visibility:'hidden'});
524 535
             $('#presentation>iframe').fadeIn(300, function() {
@@ -538,6 +549,10 @@ function setPresentationVisible(visible) {
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 557
  * Updates the large video with the given new video source.
543 558
  */
@@ -607,15 +622,20 @@ function resizeLarge() {
607 622
         $('#presentation>iframe').width(availableWidth);
608 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 631
     resizeThumbnails();
612 632
 }
613 633
 
614 634
 function resizeThumbnails() {
615 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 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 639
     var numvids = $('#remoteVideos>span:visible').length;
620 640
 
621 641
     // Remove the 1px borders arround videos and the chat width.
@@ -629,7 +649,7 @@ function resizeThumbnails() {
629 649
     }
630 650
 
631 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 653
     $('#remoteVideos>span').width(availableWidth);
634 654
     $('#remoteVideos>span').height(availableHeight);
635 655
 }

+ 3
- 3
css/main.css 查看文件

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

+ 136
- 0
etherpad.js 查看文件

@@ -0,0 +1,136 @@
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 查看文件

@@ -5,13 +5,14 @@
5 5
     <script src="libs/strophejingle.bundle.js?v=7"></script><!-- strophe.jingle bundle -->
6 6
     <script src="libs/colibri.js?v=7"></script><!-- colibri focus implementation -->
7 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 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 12
     <script src="smileys.js?v=1"></script><!-- smiley images -->
12 13
     <script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
13 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 16
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
16 17
     <link rel="stylesheet" href="css/modaldialog.css?v=3">
17 18
     <script src="libs/jquery-impromptu.js"></script>
@@ -36,11 +37,7 @@
36 37
             <div class="header_button_separator"></div>
37 38
             <a class="button" onclick='openPreziDialog();'><i title="Share prezi" class="fa fa-desktop fa-lg"></i></a>
38 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 41
         </span>
45 42
     </div>
46 43
     <div id="settings">
@@ -58,6 +55,7 @@
58 55
         <div id="largeVideoContainer" class="videocontainer">
59 56
             <div id="reloadPresentation"><a onclick='reloadPresentation();'><i title="Reload Prezi" class="fa fa-repeat fa-lg"></i></a></div>
60 57
             <div id="presentation"></div>
58
+            <div id="etherpad"></div>
61 59
             <video id="largeVideo" autoplay oncontextmenu="return false;"></video>
62 60
         </div>
63 61
         <div class="fade_line"></div>

+ 15
- 0
muc.js 查看文件

@@ -43,6 +43,13 @@ Strophe.addConnectionPlugin('emuc', {
43 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 53
         var presentation = $(pres).find('>prezi');
47 54
         if (presentation.length)
48 55
         {
@@ -188,6 +195,10 @@ Strophe.addConnectionPlugin('emuc', {
188 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 202
         if (this.presMap['medians'])
192 203
         {
193 204
             pres.c('media', {xmlns: this.presMap['medians']});
@@ -232,5 +243,9 @@ Strophe.addConnectionPlugin('emuc', {
232 243
     },
233 244
     getPrezi: function (roomjid) {
234 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
 });

Loading…
取消
儲存