diff --git a/app.js b/app.js index 3ace8c34ce..1f97574207 100644 --- a/app.js +++ b/app.js @@ -24,12 +24,12 @@ var currentVideoWidth = null; var currentVideoHeight = null; /** * Method used to calculate large video size. - * @type {function()} + * @type {function ()} */ var getVideoSize; /** * Method used to get large video position. - * @type {function()} + * @type {function ()} */ var getVideoPosition; @@ -40,9 +40,11 @@ function init() { if (RTC === null) { window.location.href = 'webrtcrequired.html'; return; + /* } else if (RTC.browser !== 'chrome') { window.location.href = 'chromeonly.html'; return; + */ } connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind'); @@ -69,9 +71,9 @@ function init() { if (config.useStunTurn) { connection.jingle.getStunAndTurnCredentials(); } - obtainAudioAndVideoPermissions(function(){ - getUserMediaWithConstraints( ['audio'], audioStreamReady, - function(error){ + obtainAudioAndVideoPermissions(function () { + getUserMediaWithConstraints(['audio'], audioStreamReady, + function (error) { console.error('failed to obtain audio stream - stop', error); }); }); @@ -88,20 +90,20 @@ function init() { * We first ask for audio and video combined stream in order to get permissions and not to ask twice. * Then we dispose the stream and continue with separate audio, video streams(required for desktop sharing). */ -function obtainAudioAndVideoPermissions(callback){ +function obtainAudioAndVideoPermissions(callback) { // This makes sense only on https sites otherwise we'll be asked for permissions every time - if(location.protocol !== 'https:') { + if (location.protocol !== 'https:') { callback(); return; } // Get AV getUserMediaWithConstraints( ['audio', 'video'], - function(avStream) { + function (avStream) { avStream.stop(); callback(); }, - function(error){ + function (error) { console.error('failed to obtain audio/video stream - stop', error); }); } @@ -110,8 +112,8 @@ function audioStreamReady(stream) { change_local_audio(stream); - if(RTC.browser !== 'firefox') { - getUserMediaWithConstraints( ['video'], videoStreamReady, videoStreamFailed, config.resolution || '360' ); + if (RTC.browser !== 'firefox') { + getUserMediaWithConstraints(['video'], videoStreamReady, videoStreamFailed, config.resolution || '360'); } else { doJoin(); } @@ -169,7 +171,7 @@ function doJoin() { roomjid += '/' + Strophe.getNodeFromJid(connection.jid); } } else { - roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0,8); + roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0, 8); } connection.emuc.doJoin(roomjid); } @@ -186,7 +188,7 @@ function change_local_video(stream, flipX) { connection.jingle.localVideo = stream; var localVideo = document.createElement('video'); - localVideo.id = 'localVideo_'+stream.id; + localVideo.id = 'localVideo_' + stream.id; localVideo.autoplay = true; localVideo.volume = 0; // is it required if audio is separated ? localVideo.oncontextmenu = function () { return false; }; @@ -196,7 +198,9 @@ function change_local_video(stream, flipX) { var localVideoSelector = $('#' + localVideo.id); // Add click handler - localVideoSelector.click(function () { handleVideoThumbClicked(localVideo.src); } ); + localVideoSelector.click(function () { + handleVideoThumbClicked(localVideo.src); + }); // Add stream ended handler stream.onended = function () { localVideoContainer.removeChild(localVideo); @@ -204,7 +208,7 @@ function change_local_video(stream, flipX) { }; // Flip video x axis if needed flipXLocalVideo = flipX; - if(flipX) { + if (flipX) { localVideoSelector.addClass("flipVideoX"); } // Attach WebRTC stream @@ -216,7 +220,7 @@ function change_local_video(stream, flipX) { $(document).bind('remotestreamadded.jingle', function (event, data, sid) { function waitForRemoteVideo(selector, sid, ssrc) { - if(selector.removed) { + if (selector.removed) { console.warn("media removed before had started", selector); return; } @@ -230,7 +234,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { // FIXME: add a class that will associate peer Jid, video.src, it's ssrc and video type // in order to get rid of too many maps - if(ssrc) { + if (ssrc) { videoSrcToSsrc[sel.attr('src')] = ssrc; } else { console.warn("No ssrc given for video", sel); @@ -250,7 +254,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { var ssrclines = SDPUtil.find_lines(sess.peerconnection.remoteDescription.sdp, 'a=ssrc'); ssrclines = ssrclines.filter(function (line) { return line.indexOf('mslabel:' + data.stream.label) !== -1; - }); + }); if (ssrclines.length) { thessrc = ssrclines[0].substring(7).split(' ')[0]; // ok to overwrite the one from focus? might save work in colibri.js @@ -305,7 +309,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { sel.hide(); RTC.attachMediaStream(sel, data.stream); - if(isVideo) { + if (isVideo) { waitForRemoteVideo(sel, sid, thessrc); } @@ -316,9 +320,9 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { sel.removed = true; sel.remove(); - var audioCount = $('#'+container.id+'>audio').length; - var videoCount = $('#'+container.id+'>video').length; - if(!audioCount && !videoCount) { + var audioCount = $('#' + container.id + '>audio').length; + var videoCount = $('#' + container.id + '>video').length; + if (!audioCount && !videoCount) { console.log("Remove whole user"); // Remove whole container container.remove(); @@ -330,14 +334,17 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) { }; // Add click handler - sel.click(function () { handleVideoThumbClicked(vid.src); }); + sel.click(function () { + handleVideoThumbClicked(vid.src); + }); // an attempt to work around https://github.com/jitsi/jitmeet/issues/32 - if (isVideo - && data.peerjid && sess.peerjid === data.peerjid && - data.stream.getVideoTracks().length === 0 && - connection.jingle.localVideo.getVideoTracks().length > 0) { - window.setTimeout(function() { + if (isVideo && + data.peerjid && sess.peerjid === data.peerjid && + data.stream.getVideoTracks().length === 0 && + connection.jingle.localVideo.getVideoTracks().length > 0) { + // + window.setTimeout(function () { sendKeyframe(sess.peerconnection); }, 3000); } @@ -361,17 +368,17 @@ function handleVideoThumbClicked(videoSrc) { * Checks if removed video is currently displayed and tries to display another one instead. * @param removedVideoSrc src stream identifier of the video. */ -function checkChangeLargeVideo(removedVideoSrc){ +function checkChangeLargeVideo(removedVideoSrc) { if (removedVideoSrc === $('#largeVideo').attr('src')) { // this is currently displayed as large // pick the last visible video in the row // if nobody else is left, this picks the local video var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0); - if(!pick) { + if (!pick) { console.info("Last visible video no longer exists"); pick = $('#remoteVideos>span[id!="mixedstream"]>video').get(0); - if(!pick) { + if (!pick) { // Try local video console.info("Fallback to local video..."); pick = $('#remoteVideos>span>span>video').get(0); @@ -396,8 +403,10 @@ function sendKeyframe(pc) { function () { pc.createAnswer( function (modifiedAnswer) { - pc.setLocalDescription(modifiedAnswer, + pc.setLocalDescription( + modifiedAnswer, function () { + // noop }, function (error) { console.log('triggerKeyframe setLocalDescription failed', error); @@ -436,7 +445,7 @@ function muteVideo(pc, unmute) { function () { console.log('mute SLD ok'); }, - function(error) { + function (error) { console.log('mute SLD error'); } ); @@ -497,11 +506,11 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) { newssrcs[type] = ssrc; directions[type] = ( - SDPUtil.find_line(media, 'a=sendrecv') - || SDPUtil.find_line(media, 'a=recvonly') - || SDPUtil.find_line('a=sendonly') - || SDPUtil.find_line('a=inactive') - || 'a=sendrecv' ).substr(2); + SDPUtil.find_line(media, 'a=sendrecv') || + SDPUtil.find_line(media, 'a=recvonly') || + SDPUtil.find_line('a=sendonly') || + SDPUtil.find_line('a=inactive') || + 'a=sendrecv').substr(2); } }); console.log('new ssrcs', newssrcs); @@ -513,7 +522,7 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) { i++; var type = mtype; // Change video type to screen - if(mtype === 'video' && isUsingScreenStream) { + if (mtype === 'video' && isUsingScreenStream) { type = 'screen'; } connection.emuc.addMediaToPresence(i, type, newssrcs[mtype], directions[mtype]); @@ -603,13 +612,13 @@ $(document).bind('left.muc', function (event, jid) { $(document).bind('presence.muc', function (event, jid, info, pres) { // Remove old ssrcs coming from the jid - Object.keys(ssrc2jid).forEach(function(ssrc){ - if(ssrc2jid[ssrc] == jid){ - delete ssrc2jid[ssrc]; - } - if(ssrc2videoType == jid){ - delete ssrc2videoType[ssrc]; - } + Object.keys(ssrc2jid).forEach(function (ssrc) { + if (ssrc2jid[ssrc] == jid) { + delete ssrc2jid[ssrc]; + } + if (ssrc2videoType == jid) { + delete ssrc2videoType[ssrc]; + } }); $(pres).find('>media[xmlns="http://estos.de/ns/mjs"]>source').each(function (idx, ssrc) { @@ -623,7 +632,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) { // might need to update the direction if participant just went from sendrecv to recvonly if (type === 'video' || type === 'screen') { var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video'); - switch(ssrc.getAttribute('direction')) { + switch (ssrc.getAttribute('direction')) { case 'sendrecv': el.show(); break; @@ -650,27 +659,24 @@ $(document).bind('passwordrequired.muc', function (event, jid) { console.log('on password required', jid); $.prompt('

Password required

' + - '', - { - persistent: true, - buttons: { "Ok": true , "Cancel": false}, - defaultButton: 1, - loaded: function(event) { - document.getElementById('lockKey').focus(); - }, - submit: function(e,v,m,f){ - if(v) - { - var lockKey = document.getElementById('lockKey'); + '', { + persistent: true, + buttons: { "Ok": true, "Cancel": false}, + defaultButton: 1, + loaded: function (event) { + document.getElementById('lockKey').focus(); + }, + submit: function (e, v, m, f) { + if (v) { + var lockKey = document.getElementById('lockKey'); - if (lockKey.value !== null) - { - setSharedKey(lockKey.value); - connection.emuc.doJoin(jid, lockKey.value); - } - } + if (lockKey.value !== null) { + setSharedKey(lockKey.value); + connection.emuc.doJoin(jid, lockKey.value); } - }); + } + } + }); }); $(document).bind('audiomuted.muc', function (event, jid, isMuted) { @@ -739,19 +745,19 @@ function updateLargeVideo(newSrc, vol) { * @param videoSrc eg. blob:https%3A//pawel.jitsi.net/9a46e0bd-131e-4d18-9c14-a9264e8db395 * @returns {boolean} */ -function isVideoSrcDesktop(videoSrc){ +function isVideoSrcDesktop(videoSrc) { // FIXME: fix this mapping mess... // figure out if large video is desktop stream or just a camera var isDesktop = false; - if(localVideoSrc === videoSrc) { + if (localVideoSrc === videoSrc) { // local video isDesktop = isUsingScreenStream; } else { // Do we have associations... var videoSsrc = videoSrcToSsrc[videoSrc]; - if(videoSsrc) { + if (videoSsrc) { var videoType = ssrc2videoType[videoSsrc]; - if(videoType) { + if (videoType) { // Finally there... isDesktop = videoType === 'screen'; } else { @@ -769,12 +775,12 @@ function isVideoSrcDesktop(videoSrc){ */ function setLargeVideoVisible(isVisible) { if (isVisible) { - $('#largeVideo').css({visibility:'visible'}); - $('.watermark').css({visibility:'visible'}); + $('#largeVideo').css({visibility: 'visible'}); + $('.watermark').css({visibility: 'visible'}); } else { - $('#largeVideo').css({visibility:'hidden'}); - $('.watermark').css({visibility:'hidden'}); + $('#largeVideo').css({visibility: 'hidden'}); + $('.watermark').css({visibility: 'hidden'}); } } @@ -789,8 +795,8 @@ function toggleVideo() { var sess = getConferenceHandler(); if (sess) { sess.toggleVideoMute( - function(isMuted){ - if(isMuted) { + function (isMuted) { + if (isMuted) { $('#video').removeClass("icon-camera"); $('#video').addClass("icon-camera icon-camera-disabled"); } else { @@ -801,7 +807,7 @@ function toggleVideo() { ); } - var sess = focus || activecall; + sess = focus || activecall; if (!sess) { return; } @@ -835,30 +841,30 @@ function toggleAudio() { * @param videoWidth the stream video width * @param videoHeight the stream video height */ -var positionLarge = function(videoWidth, videoHeight) { +var positionLarge = function (videoWidth, videoHeight) { var videoSpaceWidth = $('#videospace').width(); var videoSpaceHeight = window.innerHeight; - var videoSize = getVideoSize( videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight); + var videoSize = getVideoSize(videoWidth, + videoHeight, + videoSpaceWidth, + videoSpaceHeight); var largeVideoWidth = videoSize[0]; var largeVideoHeight = videoSize[1]; - var videoPosition = getVideoPosition( largeVideoWidth, - largeVideoHeight, - videoSpaceWidth, - videoSpaceHeight); + var videoPosition = getVideoPosition(largeVideoWidth, + largeVideoHeight, + videoSpaceWidth, + videoSpaceHeight); var horizontalIndent = videoPosition[0]; var verticalIndent = videoPosition[1]; - positionVideo( $('#largeVideo'), - largeVideoWidth, - largeVideoHeight, - horizontalIndent, verticalIndent); + positionVideo($('#largeVideo'), + largeVideoWidth, + largeVideoHeight, + horizontalIndent, verticalIndent); }; /** @@ -868,21 +874,21 @@ var positionLarge = function(videoWidth, videoHeight) { * @return an array with 2 elements, the horizontal indent and the vertical * indent */ -function getCameraVideoPosition( videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { +function getCameraVideoPosition(videoWidth, + videoHeight, + videoSpaceWidth, + videoSpaceHeight) { // Parent height isn't completely calculated when we position the video in // full screen mode and this is why we use the screen height in this case. // Need to think it further at some point and implement it properly. - var isFullScreen = document.fullScreen - || document.mozFullScreen - || document.webkitIsFullScreen; + var isFullScreen = document.fullScreen || + document.mozFullScreen || + document.webkitIsFullScreen; if (isFullScreen) videoSpaceHeight = window.innerHeight; - var horizontalIndent = (videoSpaceWidth - videoWidth)/2; - var verticalIndent = (videoSpaceHeight - videoHeight)/2; + var horizontalIndent = (videoSpaceWidth - videoWidth) / 2; + var verticalIndent = (videoSpaceHeight - videoHeight) / 2; return [horizontalIndent, verticalIndent]; } @@ -894,12 +900,12 @@ function getCameraVideoPosition( videoWidth, * @return an array with 2 elements, the horizontal indent and the vertical * indent */ -function getDesktopVideoPosition( videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { +function getDesktopVideoPosition(videoWidth, + videoHeight, + videoSpaceWidth, + videoSpaceHeight) { - var horizontalIndent = (videoSpaceWidth - videoWidth)/2; + var horizontalIndent = (videoSpaceWidth - videoWidth) / 2; var verticalIndent = 0;// Top aligned @@ -928,10 +934,10 @@ function getCameraVideoSize(videoWidth, if (availableWidth / aspectRatio < videoSpaceHeight) { availableHeight = videoSpaceHeight; - availableWidth = availableHeight*aspectRatio; + availableWidth = availableHeight * aspectRatio; } - if (availableHeight*aspectRatio < videoSpaceWidth) { + if (availableHeight * aspectRatio < videoSpaceWidth) { availableWidth = videoSpaceWidth; availableHeight = availableWidth / aspectRatio; } @@ -945,11 +951,10 @@ function getCameraVideoSize(videoWidth, * * @return an array with 2 elements, the video width and the video height */ -function getDesktopVideoSize( videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight ) -{ +function getDesktopVideoSize(videoWidth, + videoHeight, + videoSpaceWidth, + videoSpaceHeight) { if (!videoWidth) videoWidth = currentVideoWidth; if (!videoHeight) @@ -965,10 +970,10 @@ function getDesktopVideoSize( videoWidth, if (availableWidth / aspectRatio >= videoSpaceHeight) { availableHeight = videoSpaceHeight; - availableWidth = availableHeight*aspectRatio; + availableWidth = availableHeight * aspectRatio; } - if (availableHeight*aspectRatio >= videoSpaceWidth) + if (availableHeight * aspectRatio >= videoSpaceWidth) { availableWidth = videoSpaceWidth; availableHeight = availableWidth / aspectRatio; @@ -986,11 +991,11 @@ function getDesktopVideoSize( videoWidth, * @param horizontalIndent the left and right indent * @param verticalIndent the top and bottom indent */ -function positionVideo( video, - width, - height, - horizontalIndent, - verticalIndent) { +function positionVideo(video, + width, + height, + horizontalIndent, + verticalIndent) { video.width(width); video.height(height); video.css({ top: verticalIndent + 'px', @@ -1014,7 +1019,7 @@ var resizeLargeVideoContainer = function () { resizeThumbnails(); }; -var calculateThumbnailSize = function() { +var calculateThumbnailSize = function () { // Calculate the available height, which is the inner window height minus // 39px for the header minus 2px for the delimiter lines on the top and // bottom of the large video, minus the 36px space inside the remoteVideos @@ -1056,8 +1061,7 @@ $(document).ready(function () { // Set default desktop sharing method setDesktopSharing(config.desktopSharing); // Initialize Chrome extension inline installs - if(config.chromeExtensionId) - { + if (config.chromeExtensionId) { initInlineInstalls(); } @@ -1072,7 +1076,7 @@ $(document).ready(function () { }); // Listen for large video size updates document.getElementById('largeVideo') - .addEventListener('loadedmetadata', function(e){ + .addEventListener('loadedmetadata', function (e) { currentVideoWidth = this.videoWidth; currentVideoHeight = this.videoHeight; positionLarge(currentVideoWidth, currentVideoHeight); @@ -1114,12 +1118,12 @@ $(window).bind('beforeunload', function () { function disposeConference() { var handler = getConferenceHandler(); - if(handler && handler.peerconnection) { + if (handler && handler.peerconnection) { // FIXME: probably removing streams is not required and close() should be enough - if(connection.jingle.localAudio) { + if (connection.jingle.localAudio) { handler.peerconnection.removeStream(connection.jingle.localAudio); } - if(connection.jingle.localVideo) { + if (connection.jingle.localVideo) { handler.peerconnection.removeStream(connection.jingle.localVideo); } handler.peerconnection.close(); @@ -1128,7 +1132,7 @@ function disposeConference() { activecall = null; } -function dump(elem, filename){ +function dump(elem, filename) { elem = elem.parentNode; elem.download = filename || 'meetlog.json'; elem.href = 'data:application/json;charset=utf-8,\n'; @@ -1141,8 +1145,8 @@ function dump(elem, filename){ data["jingle_" + session.sid] = { updateLog: session.peerconnection.updateLog, stats: session.peerconnection.stats, - url: window.location.href} - ; + url: window.location.href + }; } }); } @@ -1173,56 +1177,57 @@ function openLockDialog() { if (focus === null) { if (sharedKey) $.prompt("This conversation is currently protected by a shared secret key.", - { - title: "Secrect key", - persistent: false - }); + { + title: "Secrect key", + persistent: false + } + ); else $.prompt("This conversation isn't currently protected by a secret key. Only the owner of the conference could set a shared key.", - { - title: "Secrect key", - persistent: false - }); - } - else { - if (sharedKey) + { + title: "Secrect key", + persistent: false + } + ); + } else { + if (sharedKey) { $.prompt("Are you sure you would like to remove your secret key?", - { - title: "Remove secrect key", - persistent: false, - buttons: { "Remove": true, "Cancel": false}, - defaultButton: 1, - submit: function(e,v,m,f){ - if(v) - { - setSharedKey(''); - lockRoom(false); - } - } - }); - else + { + title: "Remove secrect key", + persistent: false, + buttons: { "Remove": true, "Cancel": false}, + defaultButton: 1, + submit: function (e, v, m, f) { + if (v) { + setSharedKey(''); + lockRoom(false); + } + } + } + ); + } else { $.prompt('

Set a secrect key to lock your room

' + '', - { - persistent: false, - buttons: { "Save": true , "Cancel": false}, - defaultButton: 1, - loaded: function(event) { - document.getElementById('lockKey').focus(); - }, - submit: function(e,v,m,f){ - if(v) - { - var lockKey = document.getElementById('lockKey'); - - if (lockKey.value) - { - setSharedKey(Util.escapeHtml(lockKey.value)); - lockRoom(true); + { + persistent: false, + buttons: { "Save": true, "Cancel": false}, + defaultButton: 1, + loaded: function (event) { + document.getElementById('lockKey').focus(); + }, + submit: function (e, v, m, f) { + if (v) { + var lockKey = document.getElementById('lockKey'); + + if (lockKey.value) { + setSharedKey(Util.escapeHtml(lockKey.value)); + lockRoom(true); + } } - } + } } - }); + ); + } } } @@ -1230,16 +1235,17 @@ function openLockDialog() { * Opens the invite link dialog. */ function openLinkDialog() { - $.prompt('', - { - title: "Share this link with everyone you want to invite", - persistent: false, - buttons: { "Cancel": false}, - loaded: function(event) { - document.getElementById('inviteLinkRef').select(); - } - }); + $.prompt('', + { + title: "Share this link with everyone you want to invite", + persistent: false, + buttons: { "Cancel": false}, + loaded: function (event) { + document.getElementById('inviteLinkRef').select(); + } + } + ); } /** @@ -1247,40 +1253,38 @@ function openLinkDialog() { */ function openSettingsDialog() { $.prompt('

Configure your conference

' + - ' Participants join muted
' + - ' Require nicknames

' + - 'Set a secrect key to lock your room: ', - { - persistent: false, - buttons: { "Save": true , "Cancel": false}, - defaultButton: 1, - loaded: function(event) { - document.getElementById('lockKey').focus(); - }, - submit: function(e,v,m,f){ - if(v) - { - if ($('#initMuted').is(":checked")) - { - // it is checked - } + ' Participants join muted
' + + ' Require nicknames

' + + 'Set a secrect key to lock your room: ', + { + persistent: false, + buttons: { "Save": true, "Cancel": false}, + defaultButton: 1, + loaded: function (event) { + document.getElementById('lockKey').focus(); + }, + submit: function (e, v, m, f) { + if (v) { + if ($('#initMuted').is(":checked")) { + // it is checked + } - if ($('#requireNicknames').is(":checked")) - { - // it is checked - } - /* - var lockKey = document.getElementById('lockKey'); + if ($('#requireNicknames').is(":checked")) { + // it is checked + } + /* + var lockKey = document.getElementById('lockKey'); - if (lockKey.value) - { - setSharedKey(lockKey.value); - lockRoom(true); - } - */ + if (lockKey.value) + { + setSharedKey(lockKey.value); + lockRoom(true); } + */ } - }); + } + } + ); } /** @@ -1312,10 +1316,10 @@ function updateLockButton() { /** * Hides the toolbar. */ -var hideToolbar = function() { +var hideToolbar = function () { var isToolbarHover = false; - $('#header').find('*').each(function(){ + $('#header').find('*').each(function () { var id = $(this).attr('id'); if ($("#" + id + ":hover").length > 0) { isToolbarHover = true; @@ -1418,7 +1422,7 @@ function showFocusIndicator() { var session = connection.jingle.sessions[Object.keys(connection.jingle.sessions)[0]]; var focusId = 'participant_' + Strophe.getResourceFromJid(session.peerjid); var focusContainer = document.getElementById(focusId); - if(!focusContainer) { + if (!focusContainer) { console.error("No focus container!"); return; } @@ -1438,12 +1442,11 @@ function showFocusIndicator() { * Checks if container for participant identified by given peerJid exists in the document and creates it eventually. * @param peerJid peer Jid to check. */ -function ensurePeerContainerExists(peerJid){ - +function ensurePeerContainerExists(peerJid) { var peerResource = Strophe.getResourceFromJid(peerJid); var videoSpanId = 'participant_' + peerResource; - if($('#'+videoSpanId).length > 0) { + if ($('#' + videoSpanId).length > 0) { return; } @@ -1482,8 +1485,7 @@ function createFocusIndicatorElement(parentElement) { function toggleFullScreen() { var fsElement = document.documentElement; - if (!document.mozFullScreen && !document.webkitIsFullScreen){ - + if (!document.mozFullScreen && !document.webkitIsFullScreen) { //Enter Full Screen if (fsElement.mozRequestFullScreen) { fsElement.mozRequestFullScreen(); @@ -1511,13 +1513,13 @@ function showDisplayName(videoSpanId, displayName) { if (nameSpan.length > 0) { var nameSpanElement = nameSpan.get(0); - if (nameSpanElement.id === 'localDisplayName' - && $('#localDisplayName').text() !== displayName) + if (nameSpanElement.id === 'localDisplayName' && + $('#localDisplayName').text() !== displayName) { $('#localDisplayName').text(displayName); - else + } else { $('#' + videoSpanId + '_name').text(displayName); - } - else { + } + } else { var editButton = null; if (videoSpanId === 'localVideoContainer') { @@ -1532,8 +1534,7 @@ function showDisplayName(videoSpanId, displayName) { if (!editButton) { nameSpan.id = videoSpanId + '_name'; - } - else { + } else { nameSpan.id = 'localDisplayName'; $('#' + videoSpanId)[0].appendChild(editButton); @@ -1541,22 +1542,22 @@ function showDisplayName(videoSpanId, displayName) { editableText.className = 'displayname'; editableText.id = 'editDisplayName'; - if (displayName.length) - editableText.value - = displayName.substring(0, displayName.indexOf(' (me)')); + if (displayName.length) { + editableText.value = displayName.substring(0, displayName.indexOf(' (me)')); + } editableText.setAttribute('style', 'display:none;'); editableText.setAttribute('placeholder', 'ex. Jane Pink'); $('#' + videoSpanId)[0].appendChild(editableText); - $('#localVideoContainer .displayname').bind("click", function(e) { + $('#localVideoContainer .displayname').bind("click", function (e) { e.preventDefault(); $('#localDisplayName').hide(); $('#editDisplayName').show(); $('#editDisplayName').focus(); $('#editDisplayName').select(); - var inputDisplayNameHandler = function(name) { + var inputDisplayNameHandler = function (name) { if (nickname !== name) { nickname = name; window.localStorage.displayname = nickname; @@ -1661,20 +1662,21 @@ function showVideoIndicator(videoSpanId, isMuted) { * Resizes and repositions videos in full screen mode. */ $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', - function() { - resizeLargeVideoContainer(); - positionLarge(); - isFullScreen = document.fullScreen - || document.mozFullScreen - || document.webkitIsFullScreen; - - if (isFullScreen) { - setView("fullscreen"); - } - else { - setView("default"); - } -}); + function () { + resizeLargeVideoContainer(); + positionLarge(); + isFullScreen = document.fullScreen || + document.mozFullScreen || + document.webkitIsFullScreen; + + if (isFullScreen) { + setView("fullscreen"); + } + else { + setView("default"); + } + } +); /** * Sets the current view. diff --git a/chat.js b/chat.js index b9d8e9cfc9..ad7e50ba5c 100644 --- a/chat.js +++ b/chat.js @@ -1,3 +1,4 @@ +/* global $, Util, connection, nickname:true, getVideoSize, getVideoPosition, showToolbar, processReplacements */ /** * Chat related user interface. */ @@ -16,7 +17,7 @@ var Chat = (function (my) { Chat.setChatConversationMode(true); } - $('#nickinput').keydown(function(event) { + $('#nickinput').keydown(function (event) { if (event.keyCode === 13) { event.preventDefault(); var val = Util.escapeHtml(this.value); @@ -35,7 +36,7 @@ var Chat = (function (my) { } }); - $('#usermsg').keydown(function(event) { + $('#usermsg').keydown(function (event) { if (event.keyCode === 13) { event.preventDefault(); var message = Util.escapeHtml(this.value); @@ -45,14 +46,14 @@ var Chat = (function (my) { } }); - var onTextAreaResize = function() { + var onTextAreaResize = function () { resizeChatConversation(); scrollChatToBottom(); }; $('#usermsg').autosize({callback: onTextAreaResize}); $("#chatspace").bind("shown", - function() { + function () { unreadMessages = 0; setVisualNotification(false); }); @@ -82,9 +83,9 @@ var Chat = (function (my) { var escDisplayName = Util.escapeHtml(displayName); message = processReplacements(escMessage); - $('#chatconversation').append('
' - + escDisplayName + ': ' - + message + '
'); + $('#chatconversation').append('
' + + escDisplayName + ': ' + + message + '
'); $('#chatconversation').animate( { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000); }; @@ -103,15 +104,15 @@ var Chat = (function (my) { = getVideoSize(null, null, videospaceWidth, videospaceHeight); var videoWidth = videoSize[0]; var videoHeight = videoSize[1]; - var videoPosition = getVideoPosition( videoWidth, - videoHeight, - videospaceWidth, - videospaceHeight); + var videoPosition = getVideoPosition(videoWidth, + videoHeight, + videospaceWidth, + videospaceHeight); var horizontalIndent = videoPosition[0]; var verticalIndent = videoPosition[1]; if (chatspace.is(":visible")) { - videospace.animate( {right: chatSize[0], + videospace.animate({right: chatSize[0], width: videospaceWidth, height: videospaceHeight}, {queue: false, @@ -143,7 +144,7 @@ var Chat = (function (my) { height: videospaceHeight}, {queue: false, duration: 500, - complete: function() { + complete: function () { scrollChatToBottom(); chatspace.trigger('shown'); } @@ -183,9 +184,9 @@ var Chat = (function (my) { */ my.setChatConversationMode = function (isConversationMode) { if (isConversationMode) { - $('#nickname').css({visibility:"hidden"}); - $('#chatconversation').css({visibility:'visible'}); - $('#usermsg').css({visibility:'visible'}); + $('#nickname').css({visibility: 'hidden'}); + $('#chatconversation').css({visibility: 'visible'}); + $('#usermsg').css({visibility: 'visible'}); $('#usermsg').focus(); } }; @@ -205,13 +206,13 @@ var Chat = (function (my) { /** * Returns the size of the chat. */ - my.getChatSize = function() { + my.getChatSize = function () { var availableHeight = window.innerHeight; var availableWidth = window.innerWidth; var chatWidth = 200; - if (availableWidth*0.2 < 200) - chatWidth = availableWidth*0.2; + if (availableWidth * 0.2 < 200) + chatWidth = availableWidth * 0.2; return [chatWidth, availableHeight]; }; @@ -228,7 +229,7 @@ var Chat = (function (my) { $('#chatconversation').width($('#chatspace').width() - 10); $('#chatconversation') .height(window.innerHeight - 10 - parseInt(usermsgHeight)); - }; + } /** * Shows/hides a visual notification, indicating that a message has arrived. @@ -245,15 +246,15 @@ var Chat = (function (my) { var chatButtonElement = document.getElementById('chatButton').parentNode; - var leftIndent = (Util.getTextWidth(chatButtonElement) - - Util.getTextWidth(unreadMsgElement))/2; - var topIndent = (Util.getTextHeight(chatButtonElement) - - Util.getTextHeight(unreadMsgElement))/2 - 3; + var leftIndent = (Util.getTextWidth(chatButtonElement) - + Util.getTextWidth(unreadMsgElement)) / 2; + var topIndent = (Util.getTextHeight(chatButtonElement) - + Util.getTextHeight(unreadMsgElement)) / 2 - 3; unreadMsgElement.setAttribute( 'style', - 'top:' + topIndent - + '; left:' + leftIndent +';'); + 'top:' + topIndent + + '; left:' + leftIndent + ';'); if (!glower.hasClass('icon-chat-simple')) { glower.removeClass('icon-chat'); @@ -267,7 +268,7 @@ var Chat = (function (my) { } if (show && !notificationInterval) { - notificationInterval = window.setInterval(function() { + notificationInterval = window.setInterval(function () { glower.toggleClass('active'); }, 800); } @@ -282,7 +283,7 @@ var Chat = (function (my) { * Scrolls chat to the bottom. */ function scrollChatToBottom() { - setTimeout(function() { + setTimeout(function () { $('#chatconversation').scrollTop( $('#chatconversation')[0].scrollHeight); }, 5); diff --git a/desktopsharing.js b/desktopsharing.js index 8513656fbc..6a6bc79375 100644 --- a/desktopsharing.js +++ b/desktopsharing.js @@ -1,3 +1,4 @@ +/* global $, config, connection, chrome, alert, getUserMediaWithConstraints, change_local_video, getConferenceHandler */ /** * Indicates that desktop stream is currently in use(for toggle purpose). * @type {boolean} @@ -12,7 +13,7 @@ var switchInProgress = false; /** * Method used to get screen sharing stream. * - * @type {function(stream_callback, failure_callback} + * @type {function (stream_callback, failure_callback} */ var obtainDesktopStream = null; @@ -22,12 +23,161 @@ var obtainDesktopStream = null; */ var _desktopSharingEnabled = null; +/** + * Method obtains desktop stream from WebRTC 'screen' source. + * Flag 'chrome://flags/#enable-usermedia-screen-capture' must be enabled. + */ +function obtainWebRTCScreen(streamCallback, failCallback) { + getUserMediaWithConstraints( + ['screen'], + streamCallback, + failCallback + ); +} + +/** + * Constructs inline install URL for Chrome desktop streaming extension. + * The 'chromeExtensionId' must be defined in config.js. + * @returns {string} + */ +function getWebStoreInstallUrl() +{ + return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId; +} + +/** + * Checks whether extension update is required. + * @param minVersion minimal required version + * @param extVersion current extension version + * @returns {boolean} + */ +function isUpdateRequired(minVersion, extVersion) +{ + try + { + var s1 = minVersion.split('.'); + var s2 = extVersion.split('.'); + + var len = Math.max(s1.length, s2.length); + for (var i = 0; i < len; i++) + { + var n1 = 0, + n2 = 0; + + if (i < s1.length) + n1 = parseInt(s1[i]); + if (i < s2.length) + n2 = parseInt(s2[i]); + + if (isNaN(n1) || isNaN(n2)) + { + return true; + } + else if (n1 !== n2) + { + return n1 > n2; + } + } + + // will happen if boths version has identical numbers in + // their components (even if one of them is longer, has more components) + return false; + } + catch (e) + { + console.error("Failed to parse extension version", e); + return true; + } +} + + +function checkExtInstalled(isInstalledCallback) { + if (!chrome.runtime) { + // No API, so no extension for sure + isInstalledCallback(false); + } + chrome.runtime.sendMessage( + config.chromeExtensionId, + { getVersion: true }, + function (response) { + if (!response || !response.version) { + // Communication failure - assume that no endpoint exists + console.warn("Extension not installed?: " + chrome.runtime.lastError); + isInstalledCallback(false); + } else { + // Check installed extension version + var extVersion = response.version; + console.log('Extension version is: ' + extVersion); + var updateRequired = isUpdateRequired(config.minChromeExtVersion, extVersion); + if (updateRequired) { + alert( + 'Jitsi Desktop Streamer requires update. ' + + 'Changes will take effect after next Chrome restart.'); + } + isInstalledCallback(!updateRequired); + } + } + ); +} + +function doGetStreamFromExtension(streamCallback, failCallback) { + // Sends 'getStream' msg to the extension. Extension id must be defined in the config. + chrome.runtime.sendMessage( + config.chromeExtensionId, + { getStream: true}, + function (response) { + if (!response) { + failCallback(chrome.runtime.lastError); + return; + } + console.log("Response from extension: " + response); + if (response.streamId) { + getUserMediaWithConstraints( + ['desktop'], + function (stream) { + streamCallback(stream); + }, + failCallback, + null, null, null, + response.streamId); + } else { + failCallback("Extension failed to get the stream"); + } + } + ); +} +/** + * Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop' stream for returned stream token. + */ +function obtainScreenFromExtension(streamCallback, failCallback) { + checkExtInstalled( + function (isInstalled) { + if (isInstalled) { + doGetStreamFromExtension(streamCallback, failCallback); + } else { + chrome.webstore.install( + getWebStoreInstallUrl(), + function (arg) { + console.log("Extension installed successfully", arg); + // We need to reload the page in order to get the access to chrome.runtime + window.location.reload(false); + }, + function (arg) { + console.log("Failed to install the extension", arg); + failCallback(arg); + } + ); + } + } + ); +} + /** * @returns {boolean} true if desktop sharing feature is available and enabled. */ function isDesktopSharingEnabled() { - if(_desktopSharingEnabled === null){ - if(obtainDesktopStream === obtainScreenFromExtension) { + if (_desktopSharingEnabled === null) { + if (obtainDesktopStream === obtainScreenFromExtension) { // Parse chrome version var userAgent = navigator.userAgent.toLowerCase(); // We can assume that user agent is chrome, because it's enforced when 'ext' streaming method is set @@ -41,6 +191,14 @@ function isDesktopSharingEnabled() { return _desktopSharingEnabled; } +function showDesktopSharingButton() { + if (isDesktopSharingEnabled()) { + $('#desktopsharing').css({display: "inline"}); + } else { + $('#desktopsharing').css({display: "none"}); + } +} + /** * Call this method to toggle desktop sharing feature. * @param method pass "ext" to use chrome extension for desktop capture(chrome extension required), @@ -49,13 +207,13 @@ function isDesktopSharingEnabled() { */ function setDesktopSharing(method) { // Check if we are running chrome - if(!navigator.webkitGetUserMedia){ + if (!navigator.webkitGetUserMedia) { obtainDesktopStream = null; console.info("Desktop sharing disabled"); - } else if(method == "ext") { + } else if (method == "ext") { obtainDesktopStream = obtainScreenFromExtension; console.info("Using Chrome extension for desktop sharing"); - } else if(method == "webrtc") { + } else if (method == "webrtc") { obtainDesktopStream = obtainWebRTCScreen; console.info("Using Chrome WebRTC for desktop sharing"); } @@ -66,14 +224,6 @@ function setDesktopSharing(method) { showDesktopSharingButton(); } -function showDesktopSharingButton() { - if(isDesktopSharingEnabled()) { - $('#desktopsharing').css( {display:"inline"} ); - } else { - $('#desktopsharing').css( {display:"none"} ); - } -} - /** * Initializes with extension id set in config.js to support inline installs. * Host site must be selected as main website of published extension. @@ -83,14 +233,34 @@ function initInlineInstalls() $("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl()); } -/** - * Constructs inline install URL for Chrome desktop streaming extension. - * The 'chromeExtensionId' must be defined in config.js. - * @returns {string} - */ -function getWebStoreInstallUrl() -{ - return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId; +function getSwitchStreamFailed(error) { + console.error("Failed to obtain the stream to switch to", error); + switchInProgress = false; +} + +function streamSwitchDone() { + //window.setTimeout( + // function () { + switchInProgress = false; + // }, 100 + //); +} + +function newStreamCreated(stream) { + + var oldStream = connection.jingle.localVideo; + + change_local_video(stream, !isUsingScreenStream); + + var conferenceHandler = getConferenceHandler(); + if (conferenceHandler) { + // FIXME: will block switchInProgress on true value in case of exception + conferenceHandler.switchStreams(stream, oldStream, streamSwitchDone); + } else { + // We are done immediately + console.error("No conference handler"); + streamSwitchDone(); + } } /* @@ -104,28 +274,28 @@ function toggleScreenSharing() { switchInProgress = true; // Only the focus is able to set a shared key. - if(!isUsingScreenStream) + if (!isUsingScreenStream) { obtainDesktopStream( - function(stream) { + function (stream) { // We now use screen stream isUsingScreenStream = true; // Hook 'ended' event to restore camera when screen stream stops stream.addEventListener('ended', - function(e) { - if(!switchInProgress && isUsingScreenStream) { + function (e) { + if (!switchInProgress && isUsingScreenStream) { toggleScreenSharing(); } } ); newStreamCreated(stream); }, - getSwitchStreamFailed ); + getSwitchStreamFailed); } else { // Disable screen stream getUserMediaWithConstraints( ['video'], - function(stream) { + function (stream) { // We are now using camera stream isUsingScreenStream = false; newStreamCreated(stream); @@ -135,170 +305,3 @@ function toggleScreenSharing() { } } -function getSwitchStreamFailed(error) { - console.error("Failed to obtain the stream to switch to", error); - switchInProgress = false; -} - -function newStreamCreated(stream) { - - var oldStream = connection.jingle.localVideo; - - change_local_video(stream, !isUsingScreenStream); - - var conferenceHandler = getConferenceHandler(); - if(conferenceHandler) { - // FIXME: will block switchInProgress on true value in case of exception - conferenceHandler.switchStreams(stream, oldStream, streamSwitchDone); - } else { - // We are done immediately - console.error("No conference handler"); - streamSwitchDone(); - } -} - -function streamSwitchDone() { - //window.setTimeout( - // function() { - switchInProgress = false; - // }, 100 - //); -} - -/** - * Method obtains desktop stream from WebRTC 'screen' source. - * Flag 'chrome://flags/#enable-usermedia-screen-capture' must be enabled. - */ -function obtainWebRTCScreen(streamCallback, failCallback) { - getUserMediaWithConstraints( - ['screen'], - streamCallback, - failCallback - ); -} - -/** - * Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop' stream for returned stream token. - */ -function obtainScreenFromExtension(streamCallback, failCallback) { - checkExtInstalled( - function(isInstalled) { - if(isInstalled) { - doGetStreamFromExtension(streamCallback, failCallback); - } else { - chrome.webstore.install( - getWebStoreInstallUrl(), - function(arg) { - console.log("Extension installed successfully", arg); - // We need to reload the page in order to get the access to chrome.runtime - window.location.reload(false); - }, - function(arg) { - console.log("Failed to install the extension", arg); - failCallback(arg); - } - ); - } - } - ); -} - -function checkExtInstalled(isInstalledCallback) { - if(!chrome.runtime) { - // No API, so no extension for sure - isInstalledCallback(false); - } - chrome.runtime.sendMessage( - config.chromeExtensionId, - { getVersion: true }, - function(response){ - if(!response || !response.version) { - // Communication failure - assume that no endpoint exists - console.warn("Extension not installed?: "+chrome.runtime.lastError); - isInstalledCallback(false); - } else { - // Check installed extension version - var extVersion = response.version; - console.log('Extension version is: '+extVersion); - var updateRequired = isUpdateRequired(config.minChromeExtVersion, extVersion); - if(updateRequired) { - alert( - 'Jitsi Desktop Streamer requires update. ' + - 'Changes will take effect after next Chrome restart.' ); - } - isInstalledCallback(!updateRequired); - } - } - ); -} - -/** - * Checks whether extension update is required. - * @param minVersion minimal required version - * @param extVersion current extension version - * @returns {boolean} - */ -function isUpdateRequired(minVersion, extVersion) -{ - try - { - var s1 = minVersion.split('.'); - var s2 = extVersion.split('.'); - - var len = Math.max(s1.length, s2.length); - for(var i = 0; i < len; i++) - { - var n1=0,n2=0; - - if(i < s1.length) - n1 = parseInt(s1[i]); - if(i < s2.length) - n2 = parseInt(s2[i]); - - if(isNaN(n1) || isNaN(n2)) - { - return true; - } - else if(n1 !== n2) - { - return n1 > n2; - } - } - - // will happen if boths version has identical numbers in - // their components (even if one of them is longer, has more components) - return false; - } - catch(e) - { - console.error("Failed to parse extension version", e); - return true; - } -} - -function doGetStreamFromExtension(streamCallback, failCallback) { - // Sends 'getStream' msg to the extension. Extension id must be defined in the config. - chrome.runtime.sendMessage( - config.chromeExtensionId, - { getStream: true}, - function(response) { - if(!response) { - failCallback(chrome.runtime.lastError); - return; - } - console.log("Response from extension: "+response); - if(response.streamId) { - getUserMediaWithConstraints( - ['desktop'], - function(stream) { - streamCallback(stream); - }, - failCallback, - null, null, null, - response.streamId); - } else { - failCallback("Extension failed to get the stream"); - } - } - ); -} diff --git a/estos_log.js b/estos_log.js index bf7fadbcd7..f822fa7a1c 100644 --- a/estos_log.js +++ b/estos_log.js @@ -1,3 +1,4 @@ +/* global Strophe */ Strophe.addConnectionPlugin('logger', { // logs raw stanzas and makes them available for download as JSON connection: null, diff --git a/etherpad.js b/etherpad.js index 61375071a6..6bb63e2e10 100644 --- a/etherpad.js +++ b/etherpad.js @@ -1,3 +1,4 @@ +/* global $, config, Prezi, Util, connection, setLargeVideoVisible, dockToolbar */ var Etherpad = (function (my) { var etherpadName = null; var etherpadIFrame = null; @@ -15,8 +16,8 @@ var Etherpad = (function (my) { if (!name) { // In case we're the focus we generate the name. - etherpadName = Math.random().toString(36).substring(7) - + '_' + (new Date().getTime()).toString(); + etherpadName = Math.random().toString(36).substring(7) + + '_' + (new Date().getTime()).toString(); shareEtherpad(); } else @@ -41,27 +42,27 @@ var Etherpad = (function (my) { if ($('#etherpad>iframe').css('visibility') === 'hidden') { largeVideo.fadeOut(300, function () { - if (Prezi.isPresentationVisible()) - largeVideo.css({opacity:'0'}); - else { + if (Prezi.isPresentationVisible()) { + largeVideo.css({opacity: '0'}); + } else { setLargeVideoVisible(false); dockToolbar(true); } - $('#etherpad>iframe').fadeIn(300, function() { + $('#etherpad>iframe').fadeIn(300, function () { document.body.style.background = '#eeeeee'; - $('#etherpad>iframe').css({visibility:'visible'}); - $('#etherpad').css({zIndex:2}); + $('#etherpad>iframe').css({visibility: 'visible'}); + $('#etherpad').css({zIndex: 2}); }); }); } else if ($('#etherpad>iframe')) { $('#etherpad>iframe').fadeOut(300, function () { - $('#etherpad>iframe').css({visibility:'hidden'}); - $('#etherpad').css({zIndex:0}); + $('#etherpad>iframe').css({visibility: 'hidden'}); + $('#etherpad').css({zIndex: 0}); document.body.style.background = 'black'; if (!isPresentation) { - $('#largeVideo').fadeIn(300, function() { + $('#largeVideo').fadeIn(300, function () { setLargeVideoVisible(true); dockToolbar(false); }); @@ -99,7 +100,7 @@ var Etherpad = (function (my) { */ function enableEtherpadButton() { if (!$('#etherpadButton').is(":visible")) - $('#etherpadButton').css({display:'inline-block'}); + $('#etherpadButton').css({display: 'inline-block'}); } /** diff --git a/util.js b/util.js index 8363c869b5..b7c2d315cf 100644 --- a/util.js +++ b/util.js @@ -1,3 +1,4 @@ +/* global $ */ /** * Utility functions. */ @@ -8,7 +9,7 @@ var Util = (function (my) { * * @param el the element */ - my.getTextWidth = function(el) { + my.getTextWidth = function (el) { return (el.clientWidth + 1); }; @@ -17,7 +18,7 @@ var Util = (function (my) { * * @param el the element */ - my.getTextHeight = function(el) { + my.getTextHeight = function (el) { return (el.clientHeight + 1); }; @@ -26,7 +27,7 @@ var Util = (function (my) { * * @param number the number to cast */ - my.toInteger = function(number) { + my.toInteger = function (number) { return Math.round(Number(number)); }; @@ -35,27 +36,25 @@ var Util = (function (my) { * * @param id the identifier of the audio element. */ - my.playSoundNotification = function(id) { + my.playSoundNotification = function (id) { document.getElementById(id).play(); }; /** * Escapes the given text. */ - my.escapeHtml = function(unsafeText) { + my.escapeHtml = function (unsafeText) { return $('
').text(unsafeText).html(); }; /** * Returns the available video width. */ - my.getAvailableVideoWidth = function() { - var chatspaceWidth = $('#chatspace').is(":visible") - ? $('#chatspace').width() - : 0; + my.getAvailableVideoWidth = function () { + var chatspaceWidth = $('#chatspace').is(":visible") ? $('#chatspace').width() : 0; return window.innerWidth - chatspaceWidth; }; return my; -}(Util || {})); \ No newline at end of file +}(Util || {}));