Flex 4 UI
- build using gradle - launch from outside flex builder
This commit is contained in:
parent
a615ed7583
commit
785ee34453
@ -465,7 +465,7 @@ class ApiController {
|
||||
|
||||
if (redirectClient){
|
||||
String destUrl = clientURL + "?sessionToken=" + sessionToken
|
||||
log.info("Successfully joined. Redirecting to ${paramsProcessorUtil.getDefaultClientUrl()}");
|
||||
log.info("Successfully joined. Redirecting to ${destUrl}");
|
||||
redirect(url: destUrl);
|
||||
}
|
||||
else{
|
||||
@ -1399,6 +1399,8 @@ class ApiController {
|
||||
* CONFIG API
|
||||
***********************************************/
|
||||
def configXML = {
|
||||
String API_CALL = 'configXML'
|
||||
log.debug CONTROLLER_NAME + "#${API_CALL}"
|
||||
|
||||
String logoutUrl = paramsProcessorUtil.getDefaultLogoutUrl()
|
||||
boolean reject = false
|
||||
|
4
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/common/services/BaseConnection.as
Normal file → Executable file
4
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/common/services/BaseConnection.as
Normal file → Executable file
@ -31,6 +31,7 @@ package org.bigbluebutton.lib.common.services {
|
||||
|
||||
protected var _onUserCommand:Boolean;
|
||||
|
||||
|
||||
public function BaseConnection() {
|
||||
}
|
||||
|
||||
@ -150,7 +151,8 @@ package org.bigbluebutton.lib.common.services {
|
||||
}
|
||||
|
||||
protected function netASyncError(event:AsyncErrorEvent):void {
|
||||
trace(LOG + "Asynchronous code error - " + event.error);
|
||||
trace(LOG + "Asynchronous code error - " + event.error + " on " + _uri);
|
||||
trace(event.toString());
|
||||
sendConnectionFailedSignal(ConnectionFailedEvent.UNKNOWN_REASON);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.lib.common.utils
|
||||
{
|
||||
import flash.external.ExternalInterface;
|
||||
|
||||
public class QueryStringParameters {
|
||||
|
||||
private var params:Array;
|
||||
|
||||
public function collectParameters():void {
|
||||
try {
|
||||
var url:String = ExternalInterface.call("window.location.search.substring", 1);
|
||||
//var url:String = "host.pl?logouturl=http://www.google.com&host=rtmp://192.168.0.120/deskShare&room=6e87dfef-9f08-4f80-993f-c0ef5f7b999b&width=1024&height=768";
|
||||
// Remove everything before the question mark, including the question mark
|
||||
|
||||
trace("URL = " + url);
|
||||
var paramPattern:RegExp = /.*\?/;
|
||||
url = url.replace(paramPattern, "");
|
||||
|
||||
// Create an array of name=value Strings.
|
||||
params = url.split("&");
|
||||
|
||||
} catch(e:Error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function getParameter(key:String):String {
|
||||
var value:String = "";
|
||||
|
||||
for (var i:int = 0; i < params.length; i++) {
|
||||
var tempA:Array = params[i].split("=");
|
||||
trace("params key=" + String(tempA[0]).toUpperCase() + " val=" + String(tempA[1]));
|
||||
if (String(tempA[0]).toUpperCase() == key.toUpperCase()) {
|
||||
value = String(tempA[1])
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
18
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/common/utils/URLFetcher.as
Normal file → Executable file
18
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/common/utils/URLFetcher.as
Normal file → Executable file
@ -7,6 +7,7 @@ package org.bigbluebutton.lib.common.utils {
|
||||
import flash.net.URLLoaderDataFormat;
|
||||
import flash.net.URLRequest;
|
||||
import flash.net.URLRequestMethod;
|
||||
import flash.net.URLVariables;
|
||||
|
||||
import mx.utils.ObjectUtil;
|
||||
|
||||
@ -36,19 +37,26 @@ package org.bigbluebutton.lib.common.utils {
|
||||
return _failureSignal;
|
||||
}
|
||||
|
||||
public function fetch(url:String, urlRequest:URLRequest = null, dataFormat:String = URLLoaderDataFormat.TEXT):void {
|
||||
public function fetch(url:String, urlRequest:URLRequest, reqVars: URLVariables,
|
||||
dataFormat:String = URLLoaderDataFormat.TEXT):void {
|
||||
trace("Fetching " + url);
|
||||
_urlRequest = urlRequest;
|
||||
if (_urlRequest == null) {
|
||||
_urlRequest = new URLRequest();
|
||||
if (_userAgent) {
|
||||
_urlRequest["userAgent"] = _userAgent;
|
||||
}
|
||||
//if (_userAgent) {
|
||||
// _urlRequest["userAgent"] = _userAgent;
|
||||
//}
|
||||
//_urlRequest.manageCookies = true; // only available in AIR, defaults to "true"
|
||||
//_urlRequest.followRedirects = true; // only available in AIR, defaults to "true"
|
||||
_urlRequest.method = URLRequestMethod.GET;
|
||||
}
|
||||
_urlRequest.url = _responseURL = url;
|
||||
|
||||
if (reqVars != null) {
|
||||
trace("reqVars " + reqVars.toString());
|
||||
_urlRequest.data = reqVars;
|
||||
}
|
||||
|
||||
var urlLoader:URLLoader = new URLLoader();
|
||||
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
||||
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
|
||||
@ -56,7 +64,7 @@ package org.bigbluebutton.lib.common.utils {
|
||||
if (HTTPStatusEvent.HTTP_RESPONSE_STATUS) { // only available in AIR, see http://stackoverflow.com/questions/2277650/unable-to-get-http-response-code-headers-in-actionscript-3
|
||||
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, httpResponseStatusHandler);
|
||||
}
|
||||
urlLoader.dataFormat = dataFormat;
|
||||
//urlLoader.dataFormat = dataFormat;
|
||||
urlLoader.load(_urlRequest);
|
||||
}
|
||||
|
||||
|
3
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/deskshare/services/DeskshareConnection.as
Normal file → Executable file
3
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/deskshare/services/DeskshareConnection.as
Normal file → Executable file
@ -116,7 +116,8 @@ package org.bigbluebutton.lib.deskshare.services {
|
||||
}
|
||||
|
||||
public function connect():void {
|
||||
baseConnection.connect(applicationURI);
|
||||
trace("Deskshare connect");
|
||||
//baseConnection.connect(applicationURI);
|
||||
}
|
||||
|
||||
public function disconnect(onUserCommand:Boolean):void {
|
||||
|
10
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/commands/ConnectCommand.as
Normal file → Executable file
10
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/commands/ConnectCommand.as
Normal file → Executable file
@ -132,10 +132,12 @@ package org.bigbluebutton.lib.main.commands {
|
||||
audioOptions.listenOnly = userSession.userList.me.listenOnly = true;
|
||||
shareMicrophoneSignal.dispatch(audioOptions);
|
||||
}
|
||||
deskshareConnection.applicationURI = userSession.config.getConfigFor("DeskShareModule").@uri;
|
||||
deskshareConnection.room = conferenceParameters.room;
|
||||
deskshareConnection.connect();
|
||||
userSession.deskshareConnection = deskshareConnection;
|
||||
|
||||
trace("Configuring deskshare");
|
||||
//deskshareConnection.applicationURI = userSession.config.getConfigFor("DeskShareModule").@uri;
|
||||
//deskshareConnection.room = conferenceParameters.room;
|
||||
//deskshareConnection.connect();
|
||||
//userSession.deskshareConnection = deskshareConnection;
|
||||
// Query the server for chat, users, and presentation info
|
||||
chatService.sendWelcomeMessage();
|
||||
chatService.getPublicChatMessages();
|
||||
|
4
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/BigBlueButtonConnection.as
Normal file → Executable file
4
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/BigBlueButtonConnection.as
Normal file → Executable file
@ -2,9 +2,7 @@ package org.bigbluebutton.lib.main.services {
|
||||
|
||||
import flash.net.NetConnection;
|
||||
import flash.net.Responder;
|
||||
|
||||
import mx.utils.ObjectUtil;
|
||||
|
||||
import org.bigbluebutton.lib.common.services.DefaultConnectionCallback;
|
||||
import org.bigbluebutton.lib.common.services.IBaseConnection;
|
||||
import org.bigbluebutton.lib.main.models.IConferenceParameters;
|
||||
@ -91,7 +89,7 @@ package org.bigbluebutton.lib.main.services {
|
||||
var uri:String = _applicationURI + "/" + _conferenceParameters.room;
|
||||
var lockSettings:Object = {disableCam: false, disableMic: false, disablePrivateChat: false, disablePublicChat: false, lockedLayout: false, lockOnJoin: false, lockOnJoinConfigurable: false};
|
||||
var connectParams:Array = [_conferenceParameters.username, _conferenceParameters.role, _conferenceParameters.room, _conferenceParameters.voicebridge, _conferenceParameters.record, _conferenceParameters.externUserID, _conferenceParameters.internalUserID, _conferenceParameters.muteOnStart, lockSettings];
|
||||
trace(connectParams);
|
||||
trace("BBB Apps connect: " + connectParams);
|
||||
baseConnection.connect.apply(null, new Array(uri).concat(connectParams));
|
||||
}
|
||||
|
||||
|
86
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/ConfigService.as
Normal file → Executable file
86
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/ConfigService.as
Normal file → Executable file
@ -1,38 +1,66 @@
|
||||
package org.bigbluebutton.lib.main.services {
|
||||
|
||||
import flash.events.Event;
|
||||
import flash.events.HTTPStatusEvent;
|
||||
import flash.events.IOErrorEvent;
|
||||
import flash.net.URLLoader;
|
||||
import flash.net.URLRequest;
|
||||
|
||||
import org.bigbluebutton.lib.common.utils.URLFetcher;
|
||||
import org.osflash.signals.ISignal;
|
||||
import org.osflash.signals.Signal;
|
||||
import flash.net.URLRequestMethod;
|
||||
import flash.net.URLVariables;
|
||||
import org.bigbluebutton.lib.common.utils.QueryStringParameters;
|
||||
import org.osflash.signals.ISignal;
|
||||
import org.osflash.signals.Signal;
|
||||
|
||||
|
||||
public class ConfigService {
|
||||
protected var _successSignal:Signal = new Signal();
|
||||
|
||||
protected var _failureSignal:Signal = new Signal();
|
||||
|
||||
public function get successSignal():ISignal {
|
||||
return _successSignal;
|
||||
protected var _successSignal:Signal = new Signal();
|
||||
protected var _failureSignal:Signal = new Signal();
|
||||
|
||||
private var urlLoader:URLLoader;
|
||||
private var reqVars:URLVariables = new URLVariables();
|
||||
|
||||
public function get successSignal():ISignal {
|
||||
return _successSignal;
|
||||
}
|
||||
|
||||
public function get failureSignal():ISignal {
|
||||
return _failureSignal;
|
||||
}
|
||||
|
||||
public function getConfig(serverUrl:String, urlRequest:URLRequest):void {
|
||||
var p:QueryStringParameters = new QueryStringParameters();
|
||||
p.collectParameters();
|
||||
var sessionToken:String = p.getParameter("sessionToken");
|
||||
trace("sessionToken=" + sessionToken);
|
||||
reqVars.sessionToken = sessionToken;
|
||||
|
||||
urlLoader = new URLLoader();
|
||||
|
||||
var configUrl:String = serverUrl + "/bigbluebutton/api/configXML";
|
||||
|
||||
var request:URLRequest = new URLRequest(configUrl);
|
||||
request.method = URLRequestMethod.GET;
|
||||
request.data = reqVars;
|
||||
|
||||
urlLoader.addEventListener(Event.COMPLETE, handleComplete);
|
||||
urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
|
||||
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
|
||||
urlLoader.load(request);
|
||||
|
||||
}
|
||||
|
||||
public function get failureSignal():ISignal {
|
||||
return _failureSignal;
|
||||
}
|
||||
|
||||
public function getConfig(serverUrl:String, urlRequest:URLRequest):void {
|
||||
var configUrl:String = serverUrl + "/bigbluebutton/api/configXML?a=" + new Date().time;
|
||||
var fetcher:URLFetcher = new URLFetcher;
|
||||
fetcher.successSignal.add(onSuccess);
|
||||
fetcher.failureSignal.add(onFailure);
|
||||
fetcher.fetch(configUrl, urlRequest);
|
||||
}
|
||||
|
||||
protected function onSuccess(data:Object, responseUrl:String, urlRequest:URLRequest, httpStatusCode:Number = 0):void {
|
||||
successSignal.dispatch(new XML(data));
|
||||
}
|
||||
|
||||
protected function onFailure(reason:String):void {
|
||||
failureSignal.dispatch(reason);
|
||||
}
|
||||
private function httpStatusHandler(event:HTTPStatusEvent):void {
|
||||
trace("httpStatusHandler: {0}", [event]);
|
||||
}
|
||||
|
||||
private function ioErrorHandler(event:IOErrorEvent):void {
|
||||
trace("ioErrorHandler: {0}", [event]);
|
||||
failureSignal.dispatch(event.text);
|
||||
}
|
||||
|
||||
private function handleComplete(e:Event):void {
|
||||
successSignal.dispatch(new XML(e.target.data));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
10
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/EnterService.as
Normal file → Executable file
10
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/main/services/EnterService.as
Normal file → Executable file
@ -1,7 +1,9 @@
|
||||
package org.bigbluebutton.lib.main.services {
|
||||
|
||||
import flash.net.URLRequest;
|
||||
import flash.net.URLVariables;
|
||||
|
||||
import org.bigbluebutton.lib.common.utils.QueryStringParameters;
|
||||
import org.bigbluebutton.lib.common.utils.URLFetcher;
|
||||
import org.osflash.signals.ISignal;
|
||||
import org.osflash.signals.Signal;
|
||||
@ -20,10 +22,16 @@ package org.bigbluebutton.lib.main.services {
|
||||
}
|
||||
|
||||
public function enter(enterUrl:String, urlRequest:URLRequest):void {
|
||||
var p:QueryStringParameters = new QueryStringParameters();
|
||||
p.collectParameters();
|
||||
var sessionToken:String = p.getParameter("sessionToken");
|
||||
var reqVars:URLVariables = new URLVariables();
|
||||
reqVars.sessionToken = sessionToken;
|
||||
|
||||
var fetcher:URLFetcher = new URLFetcher;
|
||||
fetcher.successSignal.add(onSuccess);
|
||||
fetcher.failureSignal.add(onFailure);
|
||||
fetcher.fetch(enterUrl, urlRequest);
|
||||
fetcher.fetch(enterUrl, urlRequest, reqVars);
|
||||
}
|
||||
|
||||
protected function onSuccess(data:Object, responseUrl:String, urlRequest:URLRequest, httpStatusCode:Number = 0):void {
|
||||
|
2
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/user/services/UsersMessageReceiver.as
Normal file → Executable file
2
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/user/services/UsersMessageReceiver.as
Normal file → Executable file
@ -274,6 +274,8 @@ package org.bigbluebutton.lib.user.services {
|
||||
} else {
|
||||
// why 2 different signals for authentication??
|
||||
//userUISession.loading = false; in authentication command can break order of functions
|
||||
trace(LOG + "got here!");
|
||||
if (userSession == null) trace(LOG + "User Session is NULL!!!!");
|
||||
userSession.authTokenSignal.dispatch(true);
|
||||
}
|
||||
}
|
||||
|
2
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/video/services/ProfilesService.as
Normal file → Executable file
2
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/video/services/ProfilesService.as
Normal file → Executable file
@ -23,7 +23,7 @@ package org.bigbluebutton.lib.video.services {
|
||||
var fetcher:URLFetcher = new URLFetcher;
|
||||
fetcher.successSignal.add(onSuccess);
|
||||
fetcher.failureSignal.add(onFailure);
|
||||
fetcher.fetch(ProfileUrl, urlRequest);
|
||||
fetcher.fetch(ProfileUrl, urlRequest, null);
|
||||
}
|
||||
|
||||
protected function onSuccess(data:Object, responseUrl:String, urlRequest:URLRequest, httpStatusCode:String = null):void {
|
||||
|
1
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/video/services/VideoConnection.as
Normal file → Executable file
1
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/video/services/VideoConnection.as
Normal file → Executable file
@ -111,6 +111,7 @@ package org.bigbluebutton.lib.video.services {
|
||||
}
|
||||
|
||||
public function connect():void {
|
||||
trace("Video connect");
|
||||
baseConnection.connect(uri, conferenceParameters.meetingID, userSession.userId);
|
||||
}
|
||||
|
||||
|
1
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/voice/services/VoiceConnection.as
Normal file → Executable file
1
clients/flash/common-library/src/main/actionscript/org/bigbluebutton/lib/voice/services/VoiceConnection.as
Normal file → Executable file
@ -103,6 +103,7 @@ package org.bigbluebutton.lib.voice.services {
|
||||
_conferenceParameters = confParams;
|
||||
_listenOnly = listenOnly;
|
||||
_username = encodeURIComponent(confParams.internalUserID + "-bbbID-" + confParams.username);
|
||||
trace("Voice app connect");
|
||||
baseConnection.connect(_applicationURI, confParams.meetingID, confParams.externUserID, _username);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ additionalCompilerOptions = [
|
||||
"-target-player=11.2"
|
||||
]
|
||||
|
||||
output = 'bbb-web-client'
|
||||
|
||||
dependencies {
|
||||
merged project(':common-library')
|
||||
merged files("libs/as3-signals-utilities-async-v0.9-BETA.swc")
|
||||
|
7
clients/flash/web-client/build.sh
Executable file
7
clients/flash/web-client/build.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
rm -rf build/*
|
||||
gradle build
|
||||
|
2
clients/flash/web-client/src/main/actionscript/org/bigbluebutton/web/main/services/JoinService.as
Normal file → Executable file
2
clients/flash/web-client/src/main/actionscript/org/bigbluebutton/web/main/services/JoinService.as
Normal file → Executable file
@ -37,7 +37,7 @@ package org.bigbluebutton.web.main.services {
|
||||
var fetcher:URLFetcher = new URLFetcher();
|
||||
fetcher.successSignal.add(onSuccess);
|
||||
fetcher.failureSignal.add(onFailure);
|
||||
fetcher.fetch(joinUrl);
|
||||
fetcher.fetch(joinUrl, null, null);
|
||||
}
|
||||
|
||||
protected function onSuccess(data:Object, responseUrl:String, urlRequest:URLRequest):void {
|
||||
|
@ -20,12 +20,14 @@ package org.bigbluebutton.web.main.views {
|
||||
override public function initialize():void {
|
||||
uiSession.loadingChangeSignal.add(onLoadingChange);
|
||||
onLoadingChange(uiSession.loading, uiSession.loadingMessage);
|
||||
var tempURL:String = "http://192.168.23.53/bigbluebutton/api/join?fullName=Foo&meetingID=random-9342782&password=mp&redirect=true&checksum=0491da5c90460ed8fd1690cbbf15960bd26bc90c";
|
||||
// Call join service
|
||||
var joinSubservice:JoinService = new JoinService();
|
||||
joinSubservice.successSignal.add(joinSuccess);
|
||||
joinSubservice.failureSignal.add(joinFailure);
|
||||
joinSubservice.join(tempURL);
|
||||
joinMeetingSignal.dispatch("http://192.168.23.53");
|
||||
|
||||
// var tempURL:String = "http://192.168.23.53/bigbluebutton/api/join?fullName=Foo&meetingID=random-9342782&password=mp&redirect=true&checksum=0491da5c90460ed8fd1690cbbf15960bd26bc90c";
|
||||
// // Call join service
|
||||
// var joinSubservice:JoinService = new JoinService();
|
||||
// joinSubservice.successSignal.add(joinSuccess);
|
||||
// joinSubservice.failureSignal.add(joinFailure);
|
||||
// joinSubservice.join(tempURL);
|
||||
}
|
||||
|
||||
private function onLoadingChange(loading:Boolean, message:String):void {
|
||||
|
172
clients/flash/web-client/src/main/resources/3rd-party.html
Executable file
172
clients/flash/web-client/src/main/resources/3rd-party.html
Executable file
@ -0,0 +1,172 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">
|
||||
html, body, #flashclient { height:100%; }
|
||||
body { margin:0; padding:0; overflow:hidden; }
|
||||
#altContent { /* style alt content */ }
|
||||
</style>
|
||||
<script type="text/javascript" src="http://192.168.0.249/client/swfobject/swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
swfobject.registerObject("BigBlueButton", "11", "expressInstall.swf");
|
||||
swfobject.registerObject("WebcamPreviewStandalone", "11", "expressInstall.swf");
|
||||
swfobject.registerObject("WebcamViewStandalone", "11", "expressInstall.swf");
|
||||
</script>
|
||||
|
||||
<!--<script src="http://192.168.0.249/client/lib/jquery-1.5.1.min.js" language="javascript"></script>-->
|
||||
<script src="http://192.168.0.249/client/lib/bigbluebutton.js" language="javascript"></script>
|
||||
<script src="http://192.168.0.249/client/lib/bbb_localization.js" language="javascript"></script>
|
||||
<script src="http://192.168.0.249/client/lib/bbb_blinker.js" language="javascript"></script>
|
||||
|
||||
<script src="http://192.168.0.249/client/lib/jquery.mobile.min.js" language="javascript"></script>
|
||||
<script src="http://192.168.0.249/client/lib/jquery.json-2.4.min.js" language="javascript"></script>
|
||||
<!-- <script src="http://192.168.0.249/client/lib/getScreenId.js" language="javascript"></script> -->
|
||||
<script src="http://192.168.0.249/client/lib/jquery.cookie.js" language="javascript"></script>
|
||||
<script src="http://192.168.0.249/client/lib/jquery.dataTables.min.js" language="javascript"></script>
|
||||
|
||||
<script src="lib/getScreenId.js" language="javascript"></script>
|
||||
<script src="lib/jquery.FSRTC.js" language="javascript"></script>
|
||||
<script src="lib/jquery.jsonrpcclient.js" language="javascript"></script>
|
||||
<script src="lib/jquery.verto.js" language="javascript"></script>
|
||||
<script src="lib/Screen-Capturing.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension_share.js" language="javascript"></script>
|
||||
|
||||
<!-- <script src="http://192.168.0.249/client/lib/verto_extension.js" language="javascript"></script> -->
|
||||
<!-- <script src="http://192.168.0.249/client/lib/verto_extension_share.js" language="javascript"></script> -->
|
||||
<script src="http://192.168.0.249/client/lib/bbb_deskshare.js" language="javascript"></script>
|
||||
<script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_bridge.js"></script>
|
||||
<script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_cam_preview.js"></script>
|
||||
<script type="text/javascript" src="http://192.168.0.249/client/lib/bbb_api_cam_view.js"></script>
|
||||
<script type="text/javascript" src="http://192.168.0.249/3rd-party.js"></script>
|
||||
<script>
|
||||
window.chatLinkClicked = function(url) {
|
||||
window.open(url, '_blank');
|
||||
window.focus();
|
||||
}
|
||||
window.displayBBBClient = function() {
|
||||
var bbbc = document.getElementById("flashclient");
|
||||
var wcpc = document.getElementById("webcampreviewclient");
|
||||
wcpc.style.display = "none";
|
||||
bbbc.style.display = "block";
|
||||
}
|
||||
window.displayWCClient = function() {
|
||||
console.log("Displaying webcam preview client");
|
||||
var wcpc = document.getElementById("webcampreview");
|
||||
wcpc.style.display = "block";
|
||||
}
|
||||
window.onload = function() {
|
||||
registerListeners();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="controls">
|
||||
<button type="button" onclick="registerListeners()">Listen for Events</button>
|
||||
<button type="button" onclick="displayBBBClient()">Show BBB Client</button>
|
||||
<button type="button" onclick="displayWCClient()">Show WC Client</button>
|
||||
<button type="button" onclick="BBB.shareVideoCamera()">Share Webcam</button>
|
||||
<button type="button" onclick="BBB.stopSharingCamera()">Stop Webcam</button>
|
||||
<button type="button" onclick="BBB.switchPresenter('x8hxeozsqbk1')">Switch Presenter</button>
|
||||
<button type="button" onclick="joinVoiceConference2()">Join Voice</button>
|
||||
<button type="button" onclick="leaveVoiceConference2()">Leave Voice</button>
|
||||
<button type="button" onclick="getMyUserID()">Get My UserID</button>
|
||||
<button type="button" onclick="getMeetingID()">Get MeetingID</button>
|
||||
<button type="button" onclick="getMyRoleAsynch()">Get My Role Asynch</button>
|
||||
<button type="button" onclick="getMyRoleSynch()">Get My Role Synch</button>
|
||||
<button type="button" onclick="muteMe()">Mute Me</button>
|
||||
<button type="button" onclick="unmuteMe()">Unmute Me</button>
|
||||
<button type="button" onclick="muteAll()">Mute All</button>
|
||||
<button type="button" onclick="unmuteAll()">Unmute All</button>
|
||||
<button type="button" onclick="raiseHand(true)">Raise Hand</button>
|
||||
<button type="button" onclick="raiseHand(false)">Lower Hand</button>
|
||||
<button type="button" onclick="switchLayout('S2SVideoChat')">Switch Video Layout</button>
|
||||
<button type="button" onclick="switchLayout('S2SPresentation')">Switch Present Layout</button>
|
||||
<button type="button" onclick="lockLayout(true)">Lock Layout</button>
|
||||
<button type="button" onclick="lockLayout(false)">Unlock Layout</button>
|
||||
<button type="button" onclick="sendPublicChat()">Send Public Chat</button>
|
||||
<button type="button" onclick="sendPrivateChat()">Send Private Chat</button>
|
||||
<button type="button" onclick="amIPresenterSync()">Am I Presenter Sync</button>
|
||||
<button type="button" onclick="amIPresenterAsync()">Am I Presenter Async</button>
|
||||
<button type="button" onclick="getMyUserInfoAsynch()">User Info Async</button>
|
||||
<button type="button" onclick="getMyUserInfoSynch()">UserInfo Sync</button>
|
||||
<button type="button" onclick="queryListOfPresentations()">Query Presentations</button>
|
||||
<button type="button" onclick="displayPresentation('presentation3')">Display Presentation</button>
|
||||
<button type="button" onclick="deletePresentation('presentation3')">Delete Presentation</button>
|
||||
<form id="formUpload" name="formUpload" enctype="multipart/form-data">
|
||||
<input type="file" name="fileUpload" id="fileUpload" />
|
||||
<button type="button" onclick="uploadPresentation()">Upload Presentation</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="webcampreview" style="background-color:#FFD700;height:240px;width:320px;float:left;">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540001" width="100%" height="100%" id="WebcamPreviewStandalone" name="WebcamPreviewStandalone" align="middle">
|
||||
<param name="movie" value="http://192.168.0.249/client/WebcamPreviewStandalone.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="wmode" value="window" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="http://192.168.0.249/client/WebcamPreviewStandalone.swf?v=VERSION" width="100%" height="100%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
<div id="webcamview" style="background-color:#FFD700;height:240px;width:320px;float:left;">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540002" width="100%" height="100%" id="WebcamViewStandalone" name="WebcamViewStandalone" align="middle">
|
||||
<param name="movie" value="http://192.168.0.249/client/WebcamViewStandalone.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="wmode" value="window" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="http://192.168.0.249/client/WebcamViewStandalone.swf?v=VERSION" width="100%" height="100%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
<div id="flashclient" style="background-color:#EEEEEE;height:900px;width:1200px;float:left;">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="50%" height="50%" id="BigBlueButton" name="BigBlueButton" align="middle">
|
||||
<param name="movie" value="http://192.168.0.249/client/BigBlueButton.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="wmode" value="window" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="http://192.168.0.249/client/BigBlueButton.swf?v=VERSION" width="100%" height="90%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
<div id="update-display"/>
|
||||
<div id="notifications" aria-live="polite" role="region" aria-label="Chat Notifications"></div>
|
||||
</body>
|
||||
</html>
|
195
clients/flash/web-client/src/main/resources/BigBlueButton.html
Executable file
195
clients/flash/web-client/src/main/resources/BigBlueButton.html
Executable file
@ -0,0 +1,195 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">
|
||||
html, body, #content { height:100%; }
|
||||
body { margin:0; padding:0; overflow:hidden; }
|
||||
#altContent { /* style alt content */ }
|
||||
.visually-hidden {
|
||||
position: absolute !important;
|
||||
clip: rect(1px 1px, 1px, 1px);
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
height: 1px !important;
|
||||
width: 1px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#deployJavaPlugin {
|
||||
display : none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript" src="swfobject/swfobject.js"></script>
|
||||
<script src="lib/deployJava.js?v=VERSION" language="javascript"></script>
|
||||
<script type="text/javascript">
|
||||
// Check for Firefox 41.0.1/2 to workaround Flash hang
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1210665
|
||||
var ffHangWorkaround = function() {
|
||||
if (navigator.userAgent.indexOf("Windows") != -1 &&
|
||||
(navigator.userAgent.indexOf("Firefox/41.0") != -1 &&
|
||||
navigator.buildID > "20150928" &&
|
||||
navigator.buildID < "20151015")) {
|
||||
console.log("Browser appears to be Firefox 41.0.1 or .2 on Windows");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
//swfobject.registerObject("BigBlueButton", "11", "expressInstall.swf");
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "#869ca7";
|
||||
params.allowfullscreen = "true";
|
||||
if (ffHangWorkaround()) {
|
||||
console.log("Applying Firefox Flash hang workaround");
|
||||
// wmode = opaque causes button clicks to be sometimes unresponsive,
|
||||
// and right-click in particular is unreliable. It disables Flash
|
||||
// permission prompts on Linux (causing webcams, flash voice to be
|
||||
// unusable there). But it's better than a browser hang...
|
||||
params.wmode = "opaque";
|
||||
} else {
|
||||
params.wmode = "window";
|
||||
}
|
||||
params.allowscriptaccess = "true";
|
||||
params.seamlesstabbing = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "BigBlueButton";
|
||||
attributes.name = "BigBlueButton";
|
||||
attributes.align = "middle";
|
||||
attributes.tabIndex = 0;
|
||||
swfobject.embedSWF("bbb-web-client.swf?v=VERSION", "altFlash", "100%", "100%", "11.0.0", "expressInstall.swf", flashvars, params, attributes, embedCallback);
|
||||
|
||||
function embedCallback(e) {
|
||||
// Work around pixel alignment bug with Chrome 21 on Mac.
|
||||
// See: http://code.google.com/p/bigbluebutton/issues/detail?id=1294
|
||||
var objs = $('object');
|
||||
objs.each(function(i, o) {
|
||||
var o = $(o);
|
||||
var top = o.offset().top;
|
||||
var left = o.offset().left;
|
||||
var roundtop = Math.round(top);
|
||||
var roundleft = Math.round(left);
|
||||
o.css("position", "relative");
|
||||
if (roundtop === top) {
|
||||
} else {
|
||||
o.css("top", roundtop - top);
|
||||
}
|
||||
if (roundleft === left) {
|
||||
} else {
|
||||
o.css("left", roundleft - left);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<!--<script src="lib/jquery-1.5.1.min.js?v=VERSION" language="javascript"></script>-->
|
||||
<script src="lib/jquery-2.1.1.min.js" language="javascript"></script>
|
||||
<script src="lib/bbblogger.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bigbluebutton.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bbb_localization.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bbb_blinker.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bbb_screenshare.js" language="javascript"></script>
|
||||
|
||||
<!--<script src="lib/jquery.mobile.min.js" language="javascript"></script>-->
|
||||
<script src="lib/jquery.json-2.4.min.js" language="javascript"></script>
|
||||
<script src="lib/jquery.cookie.js" language="javascript"></script>
|
||||
<!--<script src="lib/jquery.dataTables.min.js" language="javascript"></script>-->
|
||||
|
||||
<script src="lib/getScreenId.js" language="javascript"></script>
|
||||
<script src="lib/jquery.FSRTC.js" language="javascript"></script>
|
||||
<script src="lib/jquery.jsonrpcclient.js" language="javascript"></script>
|
||||
<script src="lib/jquery.verto.js" language="javascript"></script>
|
||||
<script src="lib/Screen-Capturing.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension_share.js" language="javascript"></script>
|
||||
|
||||
<script src="lib/bbb_deskshare.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bbb_api_bridge.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/sip.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/bbb_webrtc_bridge_sip.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/weburl_regex.js?v=VERSION" language="javascript"></script>
|
||||
<script src="lib/jsnlog.min.js?v=VERSION" language="javascript"></script>
|
||||
<script>
|
||||
window.chatLinkClicked = function(url) {
|
||||
window.open(url, '_blank');
|
||||
window.focus();
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
var checkRequest = $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/html5client/check'
|
||||
});
|
||||
checkRequest.done(function(data) {
|
||||
if(typeof data.html5clientStatus !== "undefined" && data.html5clientStatus === "running" && document.getElementById('html5Section') != null) {
|
||||
document.getElementById('html5Section').style.display='inherit';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function html5() {
|
||||
// no Flash detected on the client
|
||||
var originalPath, enterRequest, authToken, meetingId, userId;
|
||||
originalPath = document.location.pathname;
|
||||
|
||||
// use the enter api to detect the meetingid, userid and authToken
|
||||
// and reuse them to join via the HTML5 client
|
||||
enterRequest = $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/bigbluebutton/api/enter'
|
||||
});
|
||||
|
||||
enterRequest.done(function(enterData) {
|
||||
meetingId = enterData.response.meetingID;
|
||||
userId = enterData.response.externUserID;
|
||||
authToken = enterData.response.authToken;
|
||||
|
||||
if ((meetingId != null) && (userId != null) && (authToken != null)) {
|
||||
// redirect to the html5 client with the received info
|
||||
// format <IP>/html5client/<meetingId>/<userId>/<authToken>
|
||||
document.location.pathname = "/html5client/"+meetingId+"/"+userId+"/"+authToken;
|
||||
} else {
|
||||
// go back to the redirection page
|
||||
document.location.pathname = originalPath;
|
||||
}
|
||||
});
|
||||
|
||||
enterRequest.fail(function(enterData, textStatus, errorThrown){
|
||||
BBBLog.debug("Enter request failed");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<audio id="remote-media" autoplay="autoplay"></audio>
|
||||
<video id="localVertoVideo" autoplay="autoplay" style="display: none;">
|
||||
<p>Your browser doesn't support HTML5 video.</p>
|
||||
</video>
|
||||
</div>
|
||||
<div id="accessibile-progress" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="visually-hidden">0 %</div>
|
||||
<button id="enterFlash" type="button" class="visually-hidden" onclick="startFlashFocus();">Set focus to client</button>
|
||||
<div id="content">
|
||||
<div id="altFlash" style="width:50%; margin-left: auto; margin-right: auto; ">
|
||||
<h2>You need Flash installed and enabled in order to use the Flash client.</h2>
|
||||
<br/>
|
||||
<div style="width:50%; margin-left: auto; margin-right: auto; ">
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<div id="html5Section" style="display:none">
|
||||
<p style="margin-left:50px;" >OR</p>
|
||||
<button type="button" onclick="html5();"><h3>Launch the HTML5 client instead</h3></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="clientReady" aria-atomic="false" aria-live="polite" class="visually-hidden"></div>
|
||||
</body>
|
||||
</html>
|
111
clients/flash/web-client/src/main/resources/BigBlueButtonTest.html
Executable file
111
clients/flash/web-client/src/main/resources/BigBlueButtonTest.html
Executable file
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<!--
|
||||
Smart developers always View Source.
|
||||
|
||||
This application was built using Adobe Flex, an open source framework
|
||||
for building rich Internet applications that get delivered via the
|
||||
Flash Player or to desktops via Adobe AIR.
|
||||
|
||||
Learn more about Flex at http://flex.org
|
||||
// -->
|
||||
<head>
|
||||
<title>BigBlueButton</title>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
|
||||
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
|
||||
the percentage of the height of its parent container, which has to be set explicitly. Fix for
|
||||
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
|
||||
if JavaScript disabled.
|
||||
-->
|
||||
<style type="text/css" media="screen">
|
||||
html, body { height:100%; }
|
||||
body { margin:0; padding:0; overflow:auto; text-align:center;
|
||||
background-color: #ffffff; }
|
||||
object:focus { outline:none; }
|
||||
#flashContent { display:none; }
|
||||
</style>
|
||||
|
||||
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
|
||||
<!-- BEGIN Browser History required section -->
|
||||
<link rel="stylesheet" type="text/css" href="history/history.css" />
|
||||
<script type="text/javascript" src="history/history.js"></script>
|
||||
<!-- END Browser History required section -->
|
||||
|
||||
<script src="jquery-1.5.1.min.js" language="javascript"></script>
|
||||
<script src="bigbluebutton.js" language="javascript"></script>
|
||||
<script src="bbb_localization.js" language="javascript"></script>
|
||||
<script src="deployJava.js" language="javascript"></script>
|
||||
<script src="bbb_blinker.js" language="javascript"></script>
|
||||
<script src="bbb_deskshare.js" language="javascript"></script>
|
||||
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
|
||||
var swfVersionStr = "10.3.0";
|
||||
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
|
||||
var xiSwfUrlStr = "playerProductInstall.swf";
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "#ffffff";
|
||||
params.allowscriptaccess = "sameDomain";
|
||||
params.allowfullscreen = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "BigBlueButton";
|
||||
attributes.name = "BigBlueButton";
|
||||
attributes.align = "middle";
|
||||
swfobject.embedSWF(
|
||||
"BigBlueButton.swf", "flashContent",
|
||||
"100%", "100%",
|
||||
swfVersionStr, xiSwfUrlStr,
|
||||
flashvars, params, attributes);
|
||||
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
|
||||
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
|
||||
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
|
||||
when JavaScript is disabled.
|
||||
-->
|
||||
<div id="flashContent">
|
||||
<p>
|
||||
To view this page ensure that Adobe Flash Player version
|
||||
10.3.0 or greater is installed.
|
||||
</p>
|
||||
<a href="http://www.adobe.com/go/getflashplayer"><img src="//www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"></a>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="BigBlueButton">
|
||||
<param name="movie" value="BigBlueButton.swf" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="BigBlueButton.swf" width="100%" height="100%">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
<!--[if gte IE 6]>-->
|
||||
<p>
|
||||
Either scripts and active content are not permitted to run or Adobe Flash Player version
|
||||
10.3.0 or greater is not installed.
|
||||
</p>
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
57
clients/flash/web-client/src/main/resources/DeskshareStandalone.html
Executable file
57
clients/flash/web-client/src/main/resources/DeskshareStandalone.html
Executable file
@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">
|
||||
html, body, #content { height:100%; }
|
||||
body { margin:0; padding:0; overflow:hidden; }
|
||||
#altContent { /* style alt content */ }
|
||||
</style>
|
||||
<script type="text/javascript" src="swfobject/swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
swfobject.registerObject("BigBlueButton", "10.3.0", "expressInstall.swf");
|
||||
</script>
|
||||
<script src="lib/jquery-2.1.1.min.js" language="javascript"></script>
|
||||
<!--<script src="lib/jquery-1.5.1.min.js" language="javascript"></script>-->
|
||||
<script src="lib/bigbluebutton.js" language="javascript"></script>
|
||||
<script src="lib/bbb_localization.js" language="javascript"></script>
|
||||
<script src="lib/bbb_blinker.js" language="javascript"></script>
|
||||
|
||||
<script src="lib/jquery.mobile.min.js" language="javascript"></script>
|
||||
<script src="lib/jquery.json-2.4.min.js" language="javascript"></script>
|
||||
<script src="lib/jquery.cookie.js" language="javascript"></script>
|
||||
<script src="lib/jquery.dataTables.min.js" language="javascript"></script>
|
||||
|
||||
<script src="lib/getScreenId.js" language="javascript"></script>
|
||||
<script src="lib/jquery.FSRTC.js" language="javascript"></script>
|
||||
<script src="lib/jquery.jsonrpcclient.js" language="javascript"></script>
|
||||
<script src="lib/jquery.verto.js" language="javascript"></script>
|
||||
<script src="lib/Screen-Capturing.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension.js" language="javascript"></script>
|
||||
<script src="lib/verto_extension_share.js" language="javascript"></script>
|
||||
|
||||
<script src="lib/bbb_deskshare.js" language="javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="BigBlueButton" name="BigBlueButton" align="middle">
|
||||
<param name="movie" value="DeskshareStandalone.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="DeskshareStandalone.swf?v=VERSION" width="100%" height="100%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="//www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
45
clients/flash/web-client/src/main/resources/EmbedBigBlueButton.html
Executable file
45
clients/flash/web-client/src/main/resources/EmbedBigBlueButton.html
Executable file
@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">
|
||||
html, body, #content { height:100%; }
|
||||
body { margin:0; padding:0; overflow:hidden; }
|
||||
#altContent { /* style alt content */ }
|
||||
</style>
|
||||
<script type="text/javascript" src="swfobject/swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
swfobject.registerObject("BigBlueButton", "11", "expressInstall.swf");
|
||||
</script>
|
||||
<script src="lib/jquery-1.5.1.min.js" language="javascript"></script>
|
||||
<script src="lib/bigbluebutton.js" language="javascript"></script>
|
||||
<script src="lib/bbb_localization.js" language="javascript"></script>
|
||||
<script src="lib/bbb_blinker.js" language="javascript"></script>
|
||||
<script src="lib/bbb_deskshare.js" language="javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="controls"/>
|
||||
<div id="content">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="BigBlueButton" name="BigBlueButton" align="middle">
|
||||
<param name="movie" value="BigBlueButton.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<param name="wmode" value="window" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="BigBlueButton.swf?v=VERSION" width="100%" height="100%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="//www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
<div id="notifications" aria-live="polite" role="region" aria-label="Chat Notifications"></div>
|
||||
</body>
|
||||
</html>
|
42
clients/flash/web-client/src/main/resources/ScreenshareStandalone.html
Executable file
42
clients/flash/web-client/src/main/resources/ScreenshareStandalone.html
Executable file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<style type="text/css" media="screen">
|
||||
html, body, #content { height:100%; }
|
||||
body { margin:0; padding:0; overflow:hidden; }
|
||||
#altContent { /* style alt content */ }
|
||||
</style>
|
||||
<script type="text/javascript" src="swfobject/swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
swfobject.registerObject("BigBlueButton", "10.3.0", "expressInstall.swf");
|
||||
</script>
|
||||
<script src="lib/jquery-1.5.1.min.js" language="javascript"></script>
|
||||
<script src="lib/bigbluebutton.js" language="javascript"></script>
|
||||
<script src="lib/bbb_localization.js" language="javascript"></script>
|
||||
<script src="lib/bbb_blinker.js" language="javascript"></script>
|
||||
<script src="lib/bbb_deskshare.js" language="javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="BigBlueButton" name="BigBlueButton" align="middle">
|
||||
<param name="movie" value="ScreenshareStandalone.swf?v=VERSION" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="allowfullscreen" value="true" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="DeskshareStandalone.swf?v=VERSION" width="100%" height="100%" align="middle">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#869ca7" />
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
clients/flash/web-client/src/main/resources/avatar.png
Executable file
BIN
clients/flash/web-client/src/main/resources/avatar.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
clients/flash/web-client/src/main/resources/bbb-deskshare-applet-0.9.0.jar
Executable file
BIN
clients/flash/web-client/src/main/resources/bbb-deskshare-applet-0.9.0.jar
Executable file
Binary file not shown.
Binary file not shown.
BIN
clients/flash/web-client/src/main/resources/bbb.gif
Executable file
BIN
clients/flash/web-client/src/main/resources/bbb.gif
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
31
clients/flash/web-client/src/main/resources/example-info-data.xml
Executable file
31
clients/flash/web-client/src/main/resources/example-info-data.xml
Executable file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" ?>
|
||||
<info>
|
||||
<returncode>SUCCESS</returncode>
|
||||
<created>2010-05-12 20:57</created>
|
||||
<topbar>
|
||||
<components>
|
||||
<label>
|
||||
<htmlLabel><![CDATA[<b>Dial In Numbers:</b>]]></htmlLabel>
|
||||
</label>
|
||||
|
||||
<combobox>
|
||||
<array>
|
||||
<value>+1 (254) 555-1212</value>
|
||||
<value>+1 (830) 555-1212</value>
|
||||
<value>+1 (504) 555-1212</value>
|
||||
<value>+1 (957) 555-1212</value>
|
||||
</array>
|
||||
|
||||
</combobox>
|
||||
<label>
|
||||
<htmlLabel><![CDATA[<b>Moderator PIN: 111222</b>]]></htmlLabel>
|
||||
</label>
|
||||
<label>
|
||||
<htmlLabel><![CDATA[<b>Attendee PIN: 222333</b>]]></htmlLabel>
|
||||
</label>
|
||||
<button label="Help" url="http://bigbluebutton.org" />
|
||||
</components>
|
||||
|
||||
</topbar>
|
||||
</info>
|
||||
|
BIN
clients/flash/web-client/src/main/resources/expressInstall.swf
Executable file
BIN
clients/flash/web-client/src/main/resources/expressInstall.swf
Executable file
Binary file not shown.
BIN
clients/flash/web-client/src/main/resources/get_flash_player.gif
Executable file
BIN
clients/flash/web-client/src/main/resources/get_flash_player.gif
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
110
clients/flash/web-client/src/main/resources/layout.xml
Executable file
110
clients/flash/web-client/src/main/resources/layout.xml
Executable file
@ -0,0 +1,110 @@
|
||||
<?xml version="1.0"?>
|
||||
<layouts>
|
||||
<layout name="bbb.layout.name.defaultlayout" default="true">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="PresentationWindow" width="0.513" height="0.684" x="0.180" y="0" />
|
||||
<window name="CaptionWindow" width="0.513" height="0.308" x="0.180" y="0.692" />
|
||||
<window name="VideoDock" width="0.177" height="0.308" x="0" y="0.687" minWidth="280" />
|
||||
<window name="ChatWindow" width="0.304" height="1" x="0.696" y="0" />
|
||||
<window name="UsersWindow" width="0.177" height="0.679" x="0" y="0" minWidth="280" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.videochat">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" width="1" height="1" x="0" y="0" order="0"/>
|
||||
<window name="ChatWindow" width="0.303125" height="0.9955703211517165" x="0.3229166666666667" y="0.9656699889258029" order="4" hidden="true" />
|
||||
<window name="PresentationWindow" minimized="true" order="1" hidden="true" />
|
||||
<window name="UsersWindow" minimized="true" hidden="true" order="2"/>
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.webcamsfocus">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" width="0.6570188133140377" height="0.9960106382978723" x="0" y="0" />
|
||||
<window name="ChatWindow" width="0.3393632416787265" height="0.5305851063829787" x="0.658465991316932" y="0" />
|
||||
<window name="UsersWindow" hidden="true" />
|
||||
<window name="PresentationWindow" width="0.34008683068017365" height="0.4601063829787234" x="0.658465991316932" y="0.535904255319149" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.presentfocus">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" minimized="true" />
|
||||
<window name="VideoDock" width="0.2923611111111111" height="0.4640957446808511" x="0.7048611111111112" y="0.535904255319149" />
|
||||
<window name="PresentationWindow" width="0.7027777777777777" height="0.9986702127659575" x="0" y="0" />
|
||||
<window name="ChatWindow" width="0.2923611111111111" height="0.5305851063829787" x="0.7048611111111112" y="0" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.lectureassistant">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" width="0.4597222222222222" height="0.9958677685950413" x="0.2263888888888889" y="0" />
|
||||
<window name="UsersWindow" width="0.22152777777777777" height="0.9958677685950413" x="0" y="0" minWidth="280" />
|
||||
<window name="PresentationWindow" width="0.3104166666666667" height="0.5537190082644629" x="0.6895833333333333" y="0" />
|
||||
<window name="VideoDock" width="0.30972222222222223" height="0.4357198347107438" x="0.6902777777777778" y="0.558870523415978" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.lecture">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" hidden="true" />
|
||||
<window name="VideoDock" width="0.2923611111111111" height="0.4640957446808511" x="0.7048611111111112" y="0.535904255319149" />
|
||||
<window name="PresentationWindow" width="0.7027777777777777" height="0.9986702127659575" x="0" y="0" />
|
||||
<window name="ChatWindow" width="0.2923611111111111" height="0.5305851063829787" x="0.7048611111111112" y="0" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.lecture" role="presenter">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" hidden="true" />
|
||||
<window name="UsersWindow" hidden="true" />
|
||||
<window name="PresentationWindow" maximized="true" />
|
||||
<window name="VideoDock" hidden="true" />
|
||||
</layout>
|
||||
<layout name="bbb.layout.name.lecture" role="moderator">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" width="0.4597222222222222" height="0.9958677685950413" x="0.2263888888888889" y="0" />
|
||||
<window name="UsersWindow" width="0.22152777777777777" height="0.9944903581267218" x="0" y="0" minWidth="280" />
|
||||
<window name="PresentationWindow" width="0.3104166666666667" height="0.5537190082644629" x="0.6895833333333333" y="0" />
|
||||
<window name="VideoDock" width="0.30972222222222223" height="0.4256198347107438" x="0.6902777777777778" y="0.568870523415978" />
|
||||
</layout>
|
||||
<!--
|
||||
<layout name="Users">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" width="0.1772793053545586" height="0.6795212765957446" x="0" y="0" />
|
||||
<window name="PresentationWindow" width="0.5137481910274964" height="0.9946808510638298" x="0.18017366136034732" y="0" />
|
||||
<window name="VideoDock" width="0.1772793053545586" height="0.30851063829787234" x="0" y="0.6875" />
|
||||
<window name="ChatWindow" width="0.3031837916063676" height="0.9960106382978723" x="0.6968162083936325" y="0" />
|
||||
</layout>
|
||||
<layout name="S2SPresentation">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="PresentationWindow" width="0.8" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
|
||||
</layout>
|
||||
<layout name="S2SVideoChat">
|
||||
<window name="NotesWindow" hidden="true" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" width="1" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
</layout>
|
||||
<layout name="Notes">
|
||||
<window name="NotesWindow" hidden="false" width="0.7" height="0.4" x="0" y="0.6" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="false" width="0.7" height="0.6" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" width="0.3" height="1" x="0.7" y="0" draggable="false" resizable="false"/>
|
||||
<window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
</layout>
|
||||
<layout name="Broadcast">
|
||||
<window name="NotesWindow" hidden="false" width="0.7" height="1" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="BroadcastWindow" hidden="false" width="0.7" height="0.9" x="0" y="0" draggable="false" resizable="false"/>
|
||||
<window name="UsersWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="VideoDock" hidden="true" draggable="false" resizable="false"/>
|
||||
<window name="ChatWindow" width="0.3" height="1" x="0.7" y="0" draggable="false" resizable="false"/>
|
||||
<window name="PresentationWindow" hidden="true" draggable="false" resizable="false"/>
|
||||
</layout>
|
||||
-->
|
||||
</layouts>
|
347
clients/flash/web-client/src/main/resources/lib/3rd-party.js
Executable file
347
clients/flash/web-client/src/main/resources/lib/3rd-party.js
Executable file
@ -0,0 +1,347 @@
|
||||
|
||||
var presenterUserID = "";
|
||||
|
||||
var registerListeners = function() {
|
||||
console.log("Listening for events.");
|
||||
BBB.listen("QueryPresentationsReplyEvent", function(bbbEvent) {
|
||||
console.log("Number of presentations [" + bbbEvent.presentations.length + "]. First presentation [" + bbbEvent.presentations[0] + "].");
|
||||
});
|
||||
BBB.listen("OpenExternalFileUploadWindowEvent", function(bbbEvent) {
|
||||
console.log("Open file upload dialog. Max file size is [" + bbbEvent.maxFileSize + "].");
|
||||
});
|
||||
BBB.listen("UserKickedOutEvent", function(bbbEvent) {
|
||||
console.log("User has been kicked [" + bbbEvent.userID + "].");
|
||||
});
|
||||
BBB.listen("SwitchedLayoutEvent", function(bbbEvent) {
|
||||
console.log("New Layout [" + bbbEvent.layoutID + "].");
|
||||
});
|
||||
BBB.listen("NewRoleEvent", function(bbbEvent) {
|
||||
console.log("New Role Event [amIPresenter=" + bbbEvent.amIPresenter + ",role=" + bbbEvent.role + ",newPresenterUserID=" + bbbEvent.newPresenterUserID + "].");
|
||||
});
|
||||
BBB.listen("SwitchedPresenterEvent", function(bbbEvent) {
|
||||
console.log("Switched Presenter [amIPresenter=" + bbbEvent.amIPresenter + ",role=" + bbbEvent.role + ",newPresenterUserID=" + bbbEvent.newPresenterUserID + "].");
|
||||
|
||||
presenterUserID = bbbEvent.newPresenterUserID;
|
||||
|
||||
if (bbbEvent.amIPresenter) {
|
||||
console.log("*** I am presenter. Am I publishing webcam?");
|
||||
BBB.listen("AmISharingCamQueryResponse", function(bbbEvent2) {
|
||||
console.log("AmISharingCamQueryResponse [isPublishing=" + bbbEvent2.isPublishing + ",camIndex=" + bbbEvent2.camIndex + "]");
|
||||
});
|
||||
BBB.amISharingWebcam();
|
||||
BBB.amISharingWebcam(function(bbbEvent3) {
|
||||
console.log("amISharingWebcam [isPublishing=" + bbbEvent3.isPublishing
|
||||
+ ",camIndex=" + bbbEvent3.camIndex
|
||||
+ ",camWidth=" + bbbEvent3.camWidth
|
||||
+ ",camHeight=" + bbbEvent3.camHeight
|
||||
+ ",camKeyFrameInterval=" + bbbEvent3.camKeyFrameInterval
|
||||
+ ",camModeFps=" + bbbEvent3.camModeFps
|
||||
+ ",camQualityBandwidth=" + bbbEvent3.camQualityBandwidth
|
||||
+ ",camQualityPicture=" + bbbEvent3.camQualityPicture
|
||||
+ "]");
|
||||
if (bbbEvent3.isPublishing) {
|
||||
CAM_PREVIEW.stopPreviewCamera(bbbEvent3.avatarURL);
|
||||
CAM_PREVIEW.previewCamera(bbbEvent3.camIndex, bbbEvent3.camWidth, bbbEvent3.camHeight, bbbEvent3.camKeyFrameInterval,
|
||||
bbbEvent3.camModeFps, bbbEvent3.camQualityBandwidth, bbbEvent3.camQualityPicture, bbbEvent3.avatarURL);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("*** I am NOT presenter. Is new presenter publishing webcam?");
|
||||
BBB.listen("IsUserPublishingCamResponse", function(bbbEvent4) {
|
||||
console.log("IsUserPublishingCamResponse [isUserPublishing=" + bbbEvent4.isUserPublishing
|
||||
+ ",uri=" + bbbEvent4.uri
|
||||
+ ",streamName=" + bbbEvent4.streamName + "]");
|
||||
});
|
||||
BBB.isUserSharingWebcam(bbbEvent.newPresenterUserID);
|
||||
BBB.isUserSharingWebcam(bbbEvent.newPresenterUserID, function(bbbEvent5) {
|
||||
console.log("isUserSharingWebcam [isUserPublishing=" + bbbEvent5.isUserPublishing
|
||||
+ ",uri=" + bbbEvent5.uri
|
||||
+ ",streamName=" + bbbEvent5.streamName + "]");
|
||||
if (presenterUserID == bbbEvent.userID) {
|
||||
CAM_VIEW.stopViewWebcamStream(bbbEvent.avatarURL);
|
||||
CAM_VIEW.viewWebcamStream(bbbEvent.uri, bbbEvent.streamName, bbbEvent5.avatarURL);
|
||||
}
|
||||
});
|
||||
CAM_PREVIEW.stopPreviewCamera(bbbEvent.avatarURL);
|
||||
}
|
||||
});
|
||||
BBB.listen("UserLeftEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + "] has left.");
|
||||
});
|
||||
BBB.listen("UserJoinedEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + ", [" + bbbEvent.userName + "] has joined.");
|
||||
});
|
||||
BBB.listen("NewPublicChatEvent", function(bbbEvent) {
|
||||
console.log("Received NewPublicChatEvent [" + bbbEvent.message + "]");
|
||||
});
|
||||
BBB.listen("NewPrivateChatEvent", function(bbbEvent) {
|
||||
console.log("Received NewPrivateChatEvent event");
|
||||
});
|
||||
BBB.listen("UserJoinedVoiceEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + "] had joined the voice conference.");
|
||||
});
|
||||
BBB.listen("UserLeftVoiceEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + "has left the voice conference.");
|
||||
});
|
||||
BBB.listen("UserVoiceMutedEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + "] is muted [" + bbbEvent.muted + "]");
|
||||
});
|
||||
BBB.listen("UserLockedVoiceEvent", function(bbbEvent) {
|
||||
console.log("User [" + bbbEvent.userID + "] is locked [" + bbbEvent.locked + "]");
|
||||
});
|
||||
BBB.listen("CamStreamSharedEvent", function(bbbEvent) {
|
||||
console.log("User CamStreamSharedEvent [" + bbbEvent.uri + "," + bbbEvent.streamName + "]");
|
||||
if (presenterUserID == bbbEvent.userID) {
|
||||
CAM_VIEW.stopViewWebcamStream(bbbEvent.avatarURL);
|
||||
CAM_VIEW.viewWebcamStream(bbbEvent.uri, bbbEvent.streamName, bbbEvent.avatarURL);
|
||||
}
|
||||
});
|
||||
BBB.listen("BroadcastingCameraStartedEvent", function(bbbEvent) {
|
||||
console.log("User BroadcastingCameraStartedEvent [" + bbbEvent.camIndex + "] [" + bbbEvent.camWidth + "]");
|
||||
if (bbbEvent.isPresenter) {
|
||||
CAM_PREVIEW.stopPreviewCamera(bbbEvent.avatarURL);
|
||||
CAM_PREVIEW.previewCamera(bbbEvent.camIndex, bbbEvent.camWidth, bbbEvent.camHeight, bbbEvent.camKeyFrameInterval,
|
||||
bbbEvent.camModeFps, bbbEvent.camQualityBandwidth, bbbEvent.camQualityPicture, bbbEvent.avatarURL);
|
||||
}
|
||||
});
|
||||
BBB.listen("BroadcastingCameraStoppedEvent", function(bbbEvent) {
|
||||
console.log("User BroadcastingCameraStoppedEvent ]");
|
||||
CAM_PREVIEW.stopPreviewCamera(bbbEvent.avatarURL);
|
||||
});
|
||||
|
||||
console.log("Listen Presentation Updates");
|
||||
BBB.listen("OfficeDocConversionSuccessEvent", function(bbbEvent) {
|
||||
console.log("Successfully converted Office document. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("OfficeDocConversionFailedEvent", function(bbbEvent) {
|
||||
console.log("Failed to convert Office document. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("SupportedDocEvent", function(bbbEvent) {
|
||||
console.log("Uploaded presentation file type is supported. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("UnsupportedDocEvent", function(bbbEvent) {
|
||||
console.log("Uploaded presentation file type is unsupported. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("PageCountFailedEvent", function(bbbEvent) {
|
||||
console.log("Failed to determine number of pages for the uploaded presentation. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("ThumbnailsUpdateEvent", function(bbbEvent) {
|
||||
console.log("Generating thumbnails for uploaded presentation. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("PageCountExceededEvent", function(bbbEvent) {
|
||||
console.log("Uploaded presentation had exceeded max number of pages. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("ConversionSuccessEvent", function(bbbEvent) {
|
||||
console.log("Successfully converted uploaded presentation. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
BBB.listen("ConversionProgressEvent", function(bbbEvent) {
|
||||
console.log("Progress update on conversion process. : " + JSON.stringify(bbbEvent));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var leaveVoiceConference2 = function () {
|
||||
BBB.leaveVoiceConference();
|
||||
}
|
||||
|
||||
var joinVoiceConference2 = function () {
|
||||
BBB.joinVoiceConference();
|
||||
}
|
||||
|
||||
var amIPresenterAsync = function() {
|
||||
BBB.listen("AmIPresenterQueryResponse", function(bbbEvent) {
|
||||
console.log("Received AmIPresenterQueryResponse event [" + bbbEvent.amIPresenter + "]");
|
||||
});
|
||||
|
||||
BBB.amIPresenter();
|
||||
}
|
||||
|
||||
var amIPresenterSync = function() {
|
||||
BBB.amIPresenter(function(amIPresenter) {
|
||||
console.log("Am I Presenter = " + amIPresenter);
|
||||
});
|
||||
}
|
||||
|
||||
var getMyUserInfoAsynch = function() {
|
||||
BBB.listen("GetMyUserInfoResponse", function(bbbEvent) {
|
||||
console.log("User info response [myUserID=" + bbbEvent.myUserID
|
||||
+ ",myUsername=" + bbbEvent.myUsername + ",myAvatarURL=" + bbbEvent.myAvatarURL
|
||||
+ ",myRole=" + bbbEvent.myRole + ",amIPresenter=" + bbbEvent.amIPresenter
|
||||
+ ",dialNumber=" + bbbEvent.dialNumber + ",voiceBridge=" + bbbEvent.voiceBridge + "].");
|
||||
|
||||
for(var key in bbbEvent.customdata){
|
||||
console.log(key + " " + bbbEvent.customdata[key]);
|
||||
}
|
||||
});
|
||||
|
||||
BBB.getMyUserInfo();
|
||||
}
|
||||
|
||||
var getMyUserInfoSynch = function() {
|
||||
BBB.getMyUserInfo(function(userInfo) {
|
||||
console.log("User info callback [myUserID=" + userInfo.myUserID
|
||||
+ ",myUsername=" + userInfo.myUsername + ",myAvatarURL=" + userInfo.myAvatarURL
|
||||
+ ",myRole=" + userInfo.myRole + ",amIPresenter=" + userInfo.amIPresenter
|
||||
+ ",dialNumber=" + userInfo.dialNumber + ",voiceBridge=" + userInfo.voiceBridge + "].");
|
||||
|
||||
for(var key in userInfo.customdata){
|
||||
console.log(key + " " + userInfo.customdata[key]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var getMyRoleAsynch = function() {
|
||||
BBB.listen("GetMyRoleResponse", function(bbbEvent) {
|
||||
console.log("Received GetMyRoleResponse event [" + bbbEvent.myRole + "]");
|
||||
});
|
||||
|
||||
BBB.getMyRole();
|
||||
}
|
||||
|
||||
var getMyRoleSynch = function() {
|
||||
BBB.getMyRole(function(myRole) {
|
||||
console.log("My role = " + myRole);
|
||||
});
|
||||
}
|
||||
|
||||
var getMyUserID = function() {
|
||||
BBB.getMyUserID(function(userID) {
|
||||
console.log("My user ID = [" + userID + "]");
|
||||
});
|
||||
}
|
||||
|
||||
var getMeetingID = function() {
|
||||
BBB.getMeetingID(function(meetingID) {
|
||||
console.log("Meeting ID = [" + meetingID + "]");
|
||||
});
|
||||
}
|
||||
|
||||
var emojiStatus = function(emojiStatus) {
|
||||
BBB.emojiStatus(emojiStatus);
|
||||
}
|
||||
|
||||
var muteMe = function() {
|
||||
BBB.muteMe();
|
||||
}
|
||||
|
||||
var unmuteMe = function() {
|
||||
BBB.unmuteMe();
|
||||
}
|
||||
|
||||
var muteAll = function() {
|
||||
BBB.muteAll();
|
||||
}
|
||||
|
||||
var unmuteAll = function() {
|
||||
BBB.unmuteAll();
|
||||
}
|
||||
|
||||
var switchLayout = function(newLayout) {
|
||||
BBB.switchLayout(newLayout);
|
||||
}
|
||||
|
||||
var lockLayout = function(lock) {
|
||||
BBB.lockLayout(lock);
|
||||
}
|
||||
|
||||
var queryListOfPresentations = function() {
|
||||
BBB.queryListOfPresentations();
|
||||
}
|
||||
|
||||
var displayPresentation = function(presentationID) {
|
||||
BBB.displayPresentation(presentationID);
|
||||
}
|
||||
|
||||
var deletePresentation = function(presentationID) {
|
||||
BBB.deletePresentation(presentationID);
|
||||
}
|
||||
|
||||
var sendPublicChat = function () {
|
||||
var message = "Hello from the Javascript API";
|
||||
BBB.sendPublicChatMessage('0x7A7A7A', "en", message);
|
||||
}
|
||||
|
||||
var sendPrivateChat = function () {
|
||||
var message = "ECHO: " + bbbEvent.message;
|
||||
BBB.sendPrivateChatMessage(bbbEvent.fromColor, bbbEvent.fromLang, message, bbbEvent.fromUserID);
|
||||
}
|
||||
|
||||
var webcamViewStandaloneAppReady = function() {
|
||||
console.log("WebcamViewStandalone App is ready.");
|
||||
BBB.getPresenterUserID(function(puid) {
|
||||
if (puid == "") {
|
||||
console.log("There is no presenter in the meeting");
|
||||
} else {
|
||||
console.log("The presenter user id is [" + puid + "]");
|
||||
// Is presenter sharing webcam? If so, get the webcam stream and display.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var webcamPreviewStandaloneAppReady = function() {
|
||||
console.log("WebcamPreviewStandalone App is ready.");
|
||||
BBB.getPresenterUserID(function(puid) {
|
||||
if (puid == "") {
|
||||
console.log("There is no presenter in the meeting");
|
||||
} else {
|
||||
console.log("The presenter user id is [" + puid + "]");
|
||||
}
|
||||
});
|
||||
// Am I presenter? If so, am I publishing my camera? If so, display my camera.
|
||||
|
||||
}
|
||||
|
||||
var uploadPresentation = function() {
|
||||
|
||||
console.log("uploadPresentation");
|
||||
|
||||
BBB.getInternalMeetingID(function(meetingID) {
|
||||
var formData = new FormData($('form')[0]);
|
||||
formData.append("presentation_name", document.getElementById('fileUpload').value.split(/(\\|\/)/g).pop());
|
||||
formData.append("conference", meetingID);
|
||||
formData.append("room", meetingID);
|
||||
|
||||
$.ajax({
|
||||
url: '/bigbluebutton/presentation/upload', //server script to process data
|
||||
type: 'POST',
|
||||
xhr: function() { // custom xhr
|
||||
myXhr = $.ajaxSettings.xhr();
|
||||
if(myXhr.upload){ // check if upload property exists
|
||||
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
|
||||
}
|
||||
return myXhr;
|
||||
},
|
||||
//Ajax events
|
||||
success: completeHandler,
|
||||
error: errorHandler,
|
||||
// Form data
|
||||
data: formData,
|
||||
//Options to tell JQuery not to process data or worry about content-type
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function progressHandlingFunction(e){
|
||||
if(e.lengthComputable){
|
||||
console.log("progress: loaded " + e.loaded + " total:" + e.total);
|
||||
}
|
||||
}
|
||||
function completeHandler(e){
|
||||
$('form')[0].reset();
|
||||
console.log("you file has been uploaded!");
|
||||
}
|
||||
function errorHandler(e){
|
||||
console.log("There was an error uploading your file.");
|
||||
}
|
159
clients/flash/web-client/src/main/resources/lib/Screen-Capturing.js
Executable file
159
clients/flash/web-client/src/main/resources/lib/Screen-Capturing.js
Executable file
@ -0,0 +1,159 @@
|
||||
// Last time updated at January 07, 2016
|
||||
// By Daniel Perrone (perroned)
|
||||
|
||||
// Latest file can be found here: https://cdn.webrtc-experiment.com/Screen-Capturing.js
|
||||
|
||||
// Muaz Khan - www.MuazKhan.com
|
||||
// MIT License - www.WebRTC-Experiment.com/licence
|
||||
// Documentation - https://github.com/muaz-khan/Chrome-Extensions/tree/master/Screen-Capturing.js
|
||||
// Demo - https://www.webrtc-experiment.com/Screen-Capturing/
|
||||
|
||||
// ___________________
|
||||
// Screen-Capturing.js
|
||||
|
||||
// Source code: https://github.com/muaz-khan/Chrome-Extensions/tree/master/desktopCapture
|
||||
// Google AppStore installation path: https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk
|
||||
|
||||
// This JavaScript file is aimed to explain steps needed to integrate above chrome extension
|
||||
// in your own webpages
|
||||
|
||||
// Usage:
|
||||
// getScreenConstraints(function(screen_constraints) {
|
||||
// navigator.webkitGetUserMedia({ video: screen_constraints }, onSuccess, onFailure );
|
||||
// });
|
||||
|
||||
// First Step: Download the extension, modify "manifest.json" and publish to Google AppStore
|
||||
// https://github.com/muaz-khan/Chrome-Extensions/tree/master/desktopCapture#how-to-publish-yourself
|
||||
|
||||
// Second Step: Listen for postMessage handler
|
||||
// postMessage is used to exchange "sourceId" between chrome extension and you webpage.
|
||||
// though, there are tons other options as well, e.g. XHR-signaling, websockets, etc.
|
||||
window.addEventListener('message', function(event) {
|
||||
if (event.origin != window.location.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
onMessageCallback(event.data);
|
||||
});
|
||||
|
||||
// and the function that handles received messages
|
||||
|
||||
function onMessageCallback(data) {
|
||||
// "cancel" button is clicked
|
||||
if (data == 'PermissionDeniedError') {
|
||||
chromeMediaSource = 'PermissionDeniedError';
|
||||
if (screenCallback) return screenCallback('PermissionDeniedError');
|
||||
else throw new Error('PermissionDeniedError');
|
||||
}
|
||||
|
||||
// extension notified his presence
|
||||
if (data == 'rtcmulticonnection-extension-loaded') {
|
||||
chromeMediaSource = 'desktop';
|
||||
}
|
||||
|
||||
// extension shared temp sourceId
|
||||
if (data.sourceId && screenCallback) {
|
||||
screenCallback(sourceId = data.sourceId);
|
||||
}
|
||||
}
|
||||
|
||||
// global variables
|
||||
var chromeMediaSource = 'screen';
|
||||
var sourceId;
|
||||
var screenCallback;
|
||||
|
||||
// this method can be used to check if chrome extension is installed & enabled.
|
||||
function isChromeExtensionAvailable(callback) {
|
||||
if (!callback) return;
|
||||
|
||||
if (chromeMediaSource == 'desktop') return callback(true);
|
||||
|
||||
// ask extension if it is available
|
||||
window.postMessage('are-you-there', '*');
|
||||
|
||||
setTimeout(function() {
|
||||
if (chromeMediaSource == 'screen') {
|
||||
callback(false);
|
||||
} else callback(true);
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// this function can be used to get "source-id" from the extension
|
||||
function getSourceId(callback) {
|
||||
if (!callback) throw '"callback" parameter is mandatory.';
|
||||
if(sourceId) return callback(sourceId);
|
||||
|
||||
screenCallback = callback;
|
||||
window.postMessage('get-sourceId', '*');
|
||||
}
|
||||
|
||||
var isFirefox = typeof window.InstallTrigger !== 'undefined';
|
||||
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
|
||||
var isChrome = !!window.chrome && !isOpera;
|
||||
|
||||
function getChromeExtensionStatus(extensionid, callback) {
|
||||
callback = normalizeCallback(callback);
|
||||
|
||||
if (isFirefox) return callback('not-chrome');
|
||||
|
||||
if (chromeMediaSource == 'desktop') return callback('installed-enabled');
|
||||
|
||||
if (arguments.length != 2) {
|
||||
callback = extensionid;
|
||||
extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; // Muaz Khan's Screen Capturing
|
||||
}
|
||||
|
||||
var image = document.createElement('img');
|
||||
image.src = 'chrome-extension://' + extensionid + '/icon.png';
|
||||
image.onload = function() {
|
||||
chromeMediaSource = 'screen';
|
||||
window.postMessage('are-you-there', '*');
|
||||
setTimeout(function() {
|
||||
callback('installed-enabled');
|
||||
}, 2000);
|
||||
};
|
||||
image.onerror = function() {
|
||||
callback('not-installed');
|
||||
};
|
||||
}
|
||||
|
||||
// this function explains how to use above methods/objects
|
||||
function getScreenConstraints(callback) {
|
||||
var firefoxScreenConstraints = {
|
||||
mozMediaSource: 'window',
|
||||
mediaSource: 'window'
|
||||
};
|
||||
|
||||
if(isFirefox) return callback(null, firefoxScreenConstraints);
|
||||
|
||||
// this statement defines getUserMedia constraints
|
||||
// that will be used to capture content of screen
|
||||
var screen_constraints = {
|
||||
mandatory: {
|
||||
chromeMediaSource: chromeMediaSource,
|
||||
maxWidth: screen.width > 1920 ? screen.width : 1920,
|
||||
maxHeight: screen.height > 1080 ? screen.height : 1080
|
||||
},
|
||||
optional: []
|
||||
};
|
||||
|
||||
// this statement verifies chrome extension availability
|
||||
// if installed and available then it will invoke extension API
|
||||
// otherwise it will fallback to command-line based screen capturing API
|
||||
sourceId = null;
|
||||
if (chromeMediaSource == 'desktop') {
|
||||
getSourceId(function() {
|
||||
screen_constraints.mandatory.chromeMediaSourceId = sourceId;
|
||||
callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// this statement sets gets 'sourceId" and sets "chromeMediaSourceId"
|
||||
if (chromeMediaSource == 'desktop') {
|
||||
screen_constraints.mandatory.chromeMediaSourceId = sourceId;
|
||||
}
|
||||
|
||||
// now invoking native getUserMedia API
|
||||
callback(null, screen_constraints);
|
||||
}
|
652
clients/flash/web-client/src/main/resources/lib/bbb_api_bridge.js
Executable file
652
clients/flash/web-client/src/main/resources/lib/bbb_api_bridge.js
Executable file
@ -0,0 +1,652 @@
|
||||
/**
|
||||
This file contains the BigBlueButton client APIs that will allow 3rd-party applications
|
||||
to embed the Flash client and interact with it through Javascript.
|
||||
|
||||
HOW TO USE:
|
||||
Some APIs allow synchronous and asynchronous calls. When using asynchronous, the 3rd-party
|
||||
JS should register as listener for events listed at the bottom of this file. For synchronous,
|
||||
3rd-party JS should pass in a callback function when calling the API.
|
||||
|
||||
For an example on how to use these APIs, see:
|
||||
|
||||
https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/resources/prod/lib/3rd-party.js
|
||||
https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/resources/prod/3rd-party.html
|
||||
|
||||
*/
|
||||
|
||||
(function(window, undefined) {
|
||||
|
||||
var BBB = {};
|
||||
|
||||
/**
|
||||
* Internal function to get the BBB embed object. Seems like we have to do this
|
||||
* each time and can't create a var for it.
|
||||
*
|
||||
* To get the object, see https://code.google.com/p/swfobject/wiki/api
|
||||
*/
|
||||
function getSwfObj() {
|
||||
return swfobject.getObjectById("BigBlueButton");
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if the current user is sharing webcam.
|
||||
*
|
||||
* Param:
|
||||
* callback - function to return the result
|
||||
*
|
||||
* If you want to instead receive an event with the result, register a listener
|
||||
* for AM_I_SHARING_CAM_RESP (see below).
|
||||
*
|
||||
*/
|
||||
BBB.amISharingWebcam = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (arguments.length == 0) {
|
||||
swfObj.amISharingCameraRequestAsync();
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.amISharingCameraRequestSync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if another user is sharing her camera.
|
||||
*
|
||||
* Param:
|
||||
* userID : the id of the user that may be sharing the camera
|
||||
* callback: function if you want to be informed synchronously. Don't pass a function
|
||||
* if you want to be informed through an event. You have to register for
|
||||
* IS_USER_PUBLISHING_CAM_RESP (see below).
|
||||
*/
|
||||
BBB.isUserSharingWebcam = function(userID, callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (arguments.length == 1) {
|
||||
swfObj.isUserPublishingCamRequestAsync(userID);
|
||||
} else {
|
||||
if (arguments.length == 2 && typeof callback === 'function') {
|
||||
callback(swfObj.isUserPublishingCamRequestSync(userID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise user's hand.
|
||||
*
|
||||
* Param:
|
||||
* emojiStatus - [string]
|
||||
*
|
||||
*/
|
||||
BBB.emojiStatus = function(emojiStatus) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Request to change emoji status [" + emojiStatus + "]");
|
||||
swfObj.emojiStatusRequest(emojiStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a switch presenter command.
|
||||
*
|
||||
* Param:
|
||||
* newPresenterUserID - the user id of the new presenter
|
||||
*
|
||||
* 3rd-party JS must listen for SWITCHED_PRESENTER (see below) to get notified
|
||||
* of switch presenter events.
|
||||
*
|
||||
*/
|
||||
BBB.switchPresenter = function(newPresenterUserID) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Request to switch presenter to [" + newPresenterUserID + "]");
|
||||
swfObj.switchPresenterRequest(newPresenterUserID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if current user is presenter.
|
||||
*
|
||||
* Params:
|
||||
* callback - function if you want a callback as response. Otherwise, you need to listen
|
||||
* for AM_I_PRESENTER_RESP (see below).
|
||||
*/
|
||||
BBB.amIPresenter = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (arguments.length == 0) {
|
||||
swfObj.amIPresenterRequestAsync();
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.amIPresenterRequestSync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eject a user.
|
||||
*
|
||||
* Params:
|
||||
* userID - userID of the user you want to eject.
|
||||
*/
|
||||
BBB.ejectUser = function(userID) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.ejectUserRequest(userID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query who is presenter.
|
||||
*
|
||||
* Params:
|
||||
* callback - function that gets executed for the response.
|
||||
*/
|
||||
BBB.getPresenterUserID = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getPresenterUserID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the current user's role.
|
||||
* Params:
|
||||
* callback - function if you want a callback as response. Otherwise, you need to listen
|
||||
* for GET_MY_ROLE_RESP (see below).
|
||||
*/
|
||||
BBB.getMyRole = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (arguments.length == 0) {
|
||||
swfObj.getMyRoleRequestAsync();
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getMyRoleRequestSync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the current user's id.
|
||||
*
|
||||
* Params:
|
||||
* callback - function that gets executed for the response.
|
||||
*/
|
||||
BBB.getMyUserID = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Getting my userID");
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getMyUserID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the current user's role.
|
||||
* Params:
|
||||
* callback - function if you want a callback as response. Otherwise, you need to listen
|
||||
* for GET_MY_ROLE_RESP (see below).
|
||||
*/
|
||||
BBB.getMyUserInfo = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (arguments.length == 0) {
|
||||
swfObj.getMyUserInfoAsync();
|
||||
} else {
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getMyUserInfoSync());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the meeting id.
|
||||
*
|
||||
* Params:
|
||||
* callback - function that gets executed for the response.
|
||||
*/
|
||||
BBB.getMeetingID = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Getting external meetingID");
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getExternalMeetingID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BBB.getInternalMeetingID = function(callback) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Getting internal meetingID");
|
||||
if (typeof callback === 'function') {
|
||||
callback(swfObj.getInternalMeetingID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the voice conference.
|
||||
*/
|
||||
BBB.joinVoiceConference = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Joining voice");
|
||||
swfObj.joinVoiceRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave the voice conference.
|
||||
*/
|
||||
BBB.leaveVoiceConference = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("Leave voice");
|
||||
swfObj.leaveVoiceRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Share user's webcam.
|
||||
*
|
||||
* Params:
|
||||
* publishInClient : (DO NOT USE - Unimplemented)
|
||||
*/
|
||||
BBB.shareVideoCamera = function(publishInClient) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
if (typeof publishInClient === 'boolean') {
|
||||
swfObj.shareVideoCamera(publishInClient);
|
||||
} else {
|
||||
swfObj.shareVideoCamera();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop share user's webcam.
|
||||
*
|
||||
*/
|
||||
BBB.stopSharingCamera = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.stopShareCameraRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute the current user.
|
||||
*
|
||||
*/
|
||||
BBB.muteMe = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.muteMeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmute the current user.
|
||||
*
|
||||
*/
|
||||
BBB.unmuteMe = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.unmuteMeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute all the users.
|
||||
*
|
||||
*/
|
||||
BBB.muteAll = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.muteAllUsersRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmute all the users.
|
||||
*
|
||||
*/
|
||||
BBB.unmuteAll = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.unmuteAllUsersRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a new layout.
|
||||
*
|
||||
* Param:
|
||||
* newLayout : name of the layout as defined in layout.xml (found in /var/www/bigbluebutton/client/conf/layout.xml)
|
||||
*
|
||||
*/
|
||||
BBB.switchLayout = function(newLayout) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.switchLayout(newLayout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the layout.
|
||||
*
|
||||
* Locking the layout means that users will have the same layout with the moderator that issued the lock command.
|
||||
* Other users won't be able to move or resize the different windows.
|
||||
*/
|
||||
BBB.lockLayout = function(lock) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.lockLayout(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to send a public chat
|
||||
* fromUserID - the external user id for the sender
|
||||
* fontColor - the color of the font to display the message
|
||||
* localeLang - the 2-char locale code (e.g. en) for the sender
|
||||
* message - the message to send
|
||||
*/
|
||||
BBB.sendPublicChatMessage = function(fontColor, localeLang, message) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.sendPublicChatRequest(fontColor, localeLang, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to send a private chat
|
||||
* fromUserID - the external user id for the sender
|
||||
* fontColor - the color of the font to display the message
|
||||
* localeLang - the 2-char locale code (e.g. en) for the sender
|
||||
* message - the message to send
|
||||
* toUserID - the external user id of the receiver
|
||||
*/
|
||||
BBB.sendPrivateChatMessage = function(fontColor, localeLang, message, toUserID) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.sendPrivateChatRequest(fontColor, localeLang, message, toUserID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to display a presentation.
|
||||
* presentationID - the presentation to display
|
||||
*/
|
||||
BBB.displayPresentation = function(presentationID) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.displayPresentationRequest(presentationID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the list of uploaded presentations.
|
||||
*/
|
||||
BBB.queryListOfPresentations = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.queryListsOfPresentationsRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to delete a presentation.
|
||||
* presentationID - the presentation to delete
|
||||
*/
|
||||
BBB.deletePresentation = function(presentationID) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.deletePresentationRequest(presentationID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
BBB.webRTCCallStarted = function(inEchoTest) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallStarted(inEchoTest);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallConnecting = function(inEchoTest) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallConnecting(inEchoTest);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallEnded = function(inEchoTest) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallEnded(inEchoTest);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallFailed = function(inEchoTest, errorcode, cause) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallFailed(inEchoTest, errorcode, cause);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallWaitingForICE = function(inEchoTest) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallWaitingForICE(inEchoTest);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallTransferring = function(inEchoTest) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallTransferring(inEchoTest);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCCallProgressCallback = function(progress) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCCallProgressCallback(progress);
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCMediaRequest = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCMediaRequest();
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCMediaSuccess = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCMediaSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
BBB.webRTCMediaFail = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.webRTCMediaFail();
|
||||
}
|
||||
}
|
||||
|
||||
BBB.javaAppletLaunched = function() {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.javaAppletLaunched();
|
||||
}
|
||||
}
|
||||
|
||||
// Third-party JS apps should use this to query if the BBB SWF file is ready to handle calls.
|
||||
BBB.isSwfClientReady = function() {
|
||||
return swfReady;
|
||||
}
|
||||
|
||||
/* ***********************************************************************************
|
||||
* Broadcasting of events to 3rd-party apps.
|
||||
*************************************************************************************/
|
||||
|
||||
/** Stores the 3rd-party app event listeners ***/
|
||||
var listeners = {};
|
||||
|
||||
/**
|
||||
* 3rd-party apps should user this method to register to listen for events.
|
||||
*/
|
||||
BBB.listen = function(eventName, handler) {
|
||||
if (typeof listeners[eventName] === 'undefined')
|
||||
listeners[eventName] = [];
|
||||
|
||||
listeners[eventName].push(handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* 3rd-party app should use this method to unregister listener for a given event.
|
||||
*/
|
||||
BBB.unlisten = function(eventName, handler) {
|
||||
if (!listeners[eventName])
|
||||
return;
|
||||
|
||||
for (var i = 0; i < listeners[eventName].length; i++) {
|
||||
if (listeners[eventName][i] === handler) {
|
||||
listeners[eventName].splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Private function to broadcast received event from the BigBlueButton Flash client to
|
||||
* 3rd-parties.
|
||||
*/
|
||||
function broadcast(bbbEvent) {
|
||||
if (!listeners[bbbEvent.eventName]) {
|
||||
console.log("No listeners for [" + bbbEvent.eventName + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < listeners[bbbEvent.eventName].length; i++) {
|
||||
console.log("Notifying listeners for [" + bbbEvent.eventName + "]");
|
||||
listeners[bbbEvent.eventName][i](bbbEvent);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
* NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
*
|
||||
* DO NOT CALL THIS METHOD FROM YOUR JS CODE.
|
||||
*
|
||||
* This is called by the BigBlueButton Flash client to inform 3rd-parties of internal events.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
* NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
*/
|
||||
BBB.handleFlashClientBroadcastEvent = function (bbbEvent) {
|
||||
console.log("Received [" + bbbEvent.eventName + "]");
|
||||
broadcast(bbbEvent);
|
||||
}
|
||||
|
||||
|
||||
// Flag to indicate that the SWF file has been loaded and ready to handle calls.
|
||||
var swfReady = false;
|
||||
|
||||
/**
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
* NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
*
|
||||
* DO NOT CALL THIS METHOD FROM YOUR JS CODE.
|
||||
*
|
||||
* This is called by the BigBlueButton Flash client to inform 3rd-parties that it is ready.
|
||||
*
|
||||
* WARNING:
|
||||
* Doesn't actually work as intended. The Flash client calls this function when it's loaded.
|
||||
* However, the client as to query the BBB server to get the status of the meeting.
|
||||
* We're working on the proper way to determining that the client is TRULY ready.
|
||||
*
|
||||
* !!! As a workaround, 3rd-party JS on init should call getUserInfo until it return NOT NULL.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
* NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
*/
|
||||
BBB.swfClientIsReady = function () {
|
||||
console.log("BigBlueButton SWF is ready.");
|
||||
swfReady = true;
|
||||
}
|
||||
|
||||
/* ********************************************************************* */
|
||||
|
||||
BBB.init = function(callback) {
|
||||
callback;
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* EVENT NAME CONSTANTS
|
||||
*
|
||||
* See https://github.com/bigbluebutton/bigbluebutton/blob/master/bigbluebutton-client/src/org/bigbluebutton/core/EventConstants.as
|
||||
*
|
||||
************************************************/
|
||||
var GET_MY_ROLE_RESP = 'GetMyRoleResponse';
|
||||
var AM_I_PRESENTER_RESP = 'AmIPresenterQueryResponse';
|
||||
var AM_I_SHARING_CAM_RESP = 'AmISharingCamQueryResponse';
|
||||
var BROADCASTING_CAM_STARTED = 'BroadcastingCameraStartedEvent';
|
||||
var BROADCASTING_CAM_STOPPED = 'BroadcastingCameraStoppedEvent';
|
||||
var I_AM_SHARING_CAM = 'IAmSharingCamEvent';
|
||||
var CAM_STREAM_SHARED = 'CamStreamSharedEvent';
|
||||
var USER_JOINED = 'UserJoinedEvent';
|
||||
var USER_LEFT = 'UserLeftEvent';
|
||||
var SWITCHED_PRESENTER = 'SwitchedPresenterEvent';
|
||||
var NEW_ROLE = 'NewRoleEvent';
|
||||
var NEW_PRIVATE_CHAT = 'NewPrivateChatEvent';
|
||||
var NEW_PUBLIC_CHAT = 'NewPublicChatEvent';
|
||||
var SWITCHED_LAYOUT = 'SwitchedLayoutEvent';
|
||||
var REMOTE_LOCKED_LAYOUT = 'RemoteLockedLayoutEvent';
|
||||
var REMOTE_UNLOCKED_LAYOUT = 'RemoteUnlockedLayoutEvent';
|
||||
var USER_JOINED_VOICE = 'UserJoinedVoiceEvent';
|
||||
var USER_LEFT_VOICE = 'UserLeftVoiceEvent';
|
||||
var USER_KICKED_OUT = 'UserKickedOutEvent';
|
||||
var USER_MUTED_VOICE = 'UserVoiceMutedEvent';
|
||||
var USER_TALKING = 'UserTalkingEvent';
|
||||
var USER_LOCKED_VOICE = 'UserLockedVoiceEvent';
|
||||
var START_PRIVATE_CHAT = "StartPrivateChatEvent";
|
||||
var GET_MY_USER_INFO_REP = "GetMyUserInfoResponse";
|
||||
var IS_USER_PUBLISHING_CAM_RESP = "IsUserPublishingCamResponse";
|
||||
|
||||
/*conversion events*/
|
||||
var OFFICE_DOC_CONVERSION_SUCCESS = "OfficeDocConversionSuccess";
|
||||
var OFFICE_DOC_CONVERSION_FAILED = "OfficeDocConversionFailed";
|
||||
var SUPPORTED_DOCUMENT = "SupportedDocument";
|
||||
var UNSUPPORTED_DOCUMENT = "UnsupportedDocument";
|
||||
var PAGE_COUNT_FAILED = "PageCountFailed";
|
||||
var THUMBNAILS_UPDATE = "ThumbnailsUpdate";
|
||||
var PAGE_COUNT_EXCEEDED = "PageCountExceeded";
|
||||
var CONVERT_SUCCESS = "ConvertSuccess";
|
||||
var CONVERT_UPDATE = "ConvertUpdate";
|
||||
|
||||
window.BBB = BBB;
|
||||
})(this);
|
||||
|
44
clients/flash/web-client/src/main/resources/lib/bbb_api_cam_preview.js
Executable file
44
clients/flash/web-client/src/main/resources/lib/bbb_api_cam_preview.js
Executable file
@ -0,0 +1,44 @@
|
||||
(function(window, undefined) {
|
||||
|
||||
var CAM_PREVIEW = {};
|
||||
|
||||
/**
|
||||
* Internal function to get the BBB embed object. Seems like we have to do this
|
||||
* each time and can't create a var for it.
|
||||
*
|
||||
* To get the object, see https://code.google.com/p/swfobject/wiki/api
|
||||
*/
|
||||
function getSwfObj() {
|
||||
return swfobject.getObjectById("WebcamPreviewStandalone");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Preview user's webcam.
|
||||
*/
|
||||
CAM_PREVIEW.previewCamera = function(camIndex, camWidth, camHeight,
|
||||
camKeyFrameInterval, camModeFps,
|
||||
camQualityBandwidth, camQualityPicture, avatarURL) {
|
||||
console.log("CAM_PREVIEW::previewCamera [" + camIndex + "]");
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.startPreviewCamera(camIndex, camWidth, camHeight, camKeyFrameInterval, camModeFps,
|
||||
camQualityBandwidth, camQualityPicture, avatarURL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop previewing user's webcam.
|
||||
*/
|
||||
CAM_PREVIEW.stopPreviewCamera = function(avatarURL) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.stopPreviewCamera(avatarURL);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("CAM_PREVIEW INITIALIZED");
|
||||
|
||||
window.CAM_PREVIEW = CAM_PREVIEW;
|
||||
})(this);
|
||||
|
42
clients/flash/web-client/src/main/resources/lib/bbb_api_cam_view.js
Executable file
42
clients/flash/web-client/src/main/resources/lib/bbb_api_cam_view.js
Executable file
@ -0,0 +1,42 @@
|
||||
(function(window, undefined) {
|
||||
|
||||
var CAM_VIEW = {};
|
||||
|
||||
/**
|
||||
* Internal function to get the BBB embed object. Seems like we have to do this
|
||||
* each time and can't create a var for it.
|
||||
*
|
||||
* To get the object, see https://code.google.com/p/swfobject/wiki/api
|
||||
*/
|
||||
function getSwfObj() {
|
||||
return swfobject.getObjectById("WebcamViewStandalone");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* View user's webcam.
|
||||
*/
|
||||
CAM_VIEW.viewWebcamStream = function(url, streamName, avatarURL) {
|
||||
console.log("CAM_VIEW::viewWebcamStream [" + url + "," + streamName + "]");
|
||||
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
console.log("CAM_VIEW::viewWebcamStream 2 [" + url + "," + streamName + "]");
|
||||
swfObj.startViewCameraStream(url, streamName, avatarURL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop viewing user's webcam.
|
||||
*/
|
||||
CAM_VIEW.stopViewWebcamStream = function(avatarURL) {
|
||||
var swfObj = getSwfObj();
|
||||
if (swfObj) {
|
||||
swfObj.stopViewCameraStream(avatarURL);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("CAM_VIEW INITIALIZED");
|
||||
window.CAM_VIEW = CAM_VIEW;
|
||||
})(this);
|
||||
|
142
clients/flash/web-client/src/main/resources/lib/bbb_blinker.js
Executable file
142
clients/flash/web-client/src/main/resources/lib/bbb_blinker.js
Executable file
@ -0,0 +1,142 @@
|
||||
function setTitle(title){
|
||||
document.title= "BigBlueButton - " + title;
|
||||
}
|
||||
|
||||
function clientReady(message){
|
||||
var target = document.getElementById("clientReady");
|
||||
if (target) target.innerHTML = message;
|
||||
}
|
||||
|
||||
function setProgressBar(percent){
|
||||
var bar = document.getElementById("accessibile-progress");
|
||||
if (bar) {
|
||||
bar.setAttribute("aria-valuenow", percent);
|
||||
bar.innerHTML = percent + " " + "%";
|
||||
}
|
||||
}
|
||||
|
||||
function removeProgressBar(){
|
||||
var bar = document.getElementById("accessibile-progress");
|
||||
if (bar) bar.parentNode.removeChild(bar);
|
||||
}
|
||||
|
||||
function determineModifier()
|
||||
{
|
||||
var browser = determineBrowser()[0];
|
||||
var modifier;
|
||||
if (browser == "Firefox"){
|
||||
modifier = "control+";
|
||||
}
|
||||
else if (browser == "Chrome"){
|
||||
modifier = "control+";
|
||||
}
|
||||
else if (browser == "Microsoft Internet Explorer"){
|
||||
modifier = "control+shift+";
|
||||
}
|
||||
//else if (browser == "Safari"){
|
||||
// modifier = "control+shift+";
|
||||
//}
|
||||
else{
|
||||
modifier = "control+shift+";
|
||||
}
|
||||
return modifier;
|
||||
}
|
||||
|
||||
function determineGlobalModifier()
|
||||
{
|
||||
var browser = determineBrowser()[0];
|
||||
var modifier;
|
||||
if (browser == "Firefox"){
|
||||
modifier = "control+shift+";
|
||||
}
|
||||
else if (browser == "Chrome"){
|
||||
modifier = "control+shift+";
|
||||
}
|
||||
else if (browser == "Microsoft Internet Explorer"){
|
||||
modifier = "control+alt+";
|
||||
}
|
||||
//else if (browser == "Safari"){
|
||||
// modifier = "control+alt";
|
||||
//}
|
||||
else{
|
||||
modifier = "control+alt+";
|
||||
}
|
||||
return modifier;
|
||||
}
|
||||
|
||||
function determineBrowser()
|
||||
{
|
||||
// Browser name extraction code provided by http://www.javascripter.net/faq/browsern.htm
|
||||
var nVer = navigator.appVersion;
|
||||
var nAgt = navigator.userAgent;
|
||||
var browserName = navigator.appName;
|
||||
var fullVersion = ''+parseFloat(navigator.appVersion);
|
||||
var majorVersion = parseInt(navigator.appVersion,10);
|
||||
var nameOffset,verOffset,ix;
|
||||
|
||||
// In Opera, the true version is after "Opera" or after "Version"
|
||||
if ((verOffset=nAgt.indexOf("Opera"))!=-1) {
|
||||
browserName = "Opera";
|
||||
fullVersion = nAgt.substring(verOffset+6);
|
||||
if ((verOffset=nAgt.indexOf("Version"))!=-1)
|
||||
fullVersion = nAgt.substring(verOffset+8);
|
||||
}
|
||||
// In MSIE, the true version is after "MSIE" in userAgent
|
||||
else if ((verOffset=nAgt.indexOf("MSIE"))!=-1) {
|
||||
browserName = "Microsoft Internet Explorer";
|
||||
fullVersion = nAgt.substring(verOffset+5);
|
||||
}
|
||||
// In Puffin, the true version is after "Puffin" in userAgent
|
||||
else if ((verOffset=nAgt.indexOf("Puffin"))!=-1) {
|
||||
browserName = "Puffin";
|
||||
fullVersion = nAgt.substring(verOffset+7);
|
||||
}
|
||||
// search for Edge before Chrome or Safari because Microsoft
|
||||
// includes Chrome and Safari user agents in Edge's UA
|
||||
// In Microsoft Edge, the true version is the last chunk of the UA
|
||||
// it follows "Edge"
|
||||
else if ((verOffset=nAgt.indexOf("Edge"))!=-1) {
|
||||
browserName = "Edge";
|
||||
// "Edge".length = 4, plus 1 character for the trailing slash
|
||||
fullVersion = nAgt.substring(verOffset+5);
|
||||
}
|
||||
// In Chrome, the true version is after "Chrome"
|
||||
else if ((verOffset=nAgt.indexOf("Chrome"))!=-1) {
|
||||
browserName = "Chrome";
|
||||
fullVersion = nAgt.substring(verOffset+7);
|
||||
}
|
||||
// In Safari, the true version is after "Safari" or after "Version"
|
||||
else if ((verOffset=nAgt.indexOf("Safari"))!=-1) {
|
||||
browserName = "Safari";
|
||||
fullVersion = nAgt.substring(verOffset+7);
|
||||
if ((verOffset=nAgt.indexOf("Version"))!=-1)
|
||||
fullVersion = nAgt.substring(verOffset+8);
|
||||
}
|
||||
// In Firefox, the true version is after "Firefox"
|
||||
else if ((verOffset=nAgt.indexOf("Firefox"))!=-1) {
|
||||
browserName = "Firefox";
|
||||
fullVersion = nAgt.substring(verOffset+8);
|
||||
}
|
||||
// In most other browsers, "name/version" is at the end of userAgent
|
||||
else if ( (nameOffset=nAgt.lastIndexOf(' ')+1) < (verOffset=nAgt.lastIndexOf('/')) )
|
||||
{
|
||||
browserName = nAgt.substring(nameOffset,verOffset);
|
||||
fullVersion = nAgt.substring(verOffset+1);
|
||||
if (browserName.toLowerCase()==browserName.toUpperCase()) {
|
||||
browserName = navigator.appName;
|
||||
}
|
||||
}
|
||||
// trim the fullVersion string at semicolon/space if present
|
||||
if ((ix=fullVersion.indexOf(";"))!=-1)
|
||||
fullVersion=fullVersion.substring(0,ix);
|
||||
if ((ix=fullVersion.indexOf(" "))!=-1)
|
||||
fullVersion=fullVersion.substring(0,ix);
|
||||
|
||||
majorVersion = parseInt(''+fullVersion,10);
|
||||
if (isNaN(majorVersion)) {
|
||||
fullVersion = ''+parseFloat(navigator.appVersion);
|
||||
majorVersion = parseInt(navigator.appVersion,10);
|
||||
}
|
||||
|
||||
return [browserName, majorVersion, fullVersion];
|
||||
}
|
174
clients/flash/web-client/src/main/resources/lib/bbb_deskshare.js
Executable file
174
clients/flash/web-client/src/main/resources/lib/bbb_deskshare.js
Executable file
@ -0,0 +1,174 @@
|
||||
if (!window.console) window.console = {};
|
||||
if (!window.console.log) window.console.log = function () { };
|
||||
|
||||
function startApplet(IP, useTLS , roomNumber, fullScreen, useSVC2)
|
||||
{
|
||||
var deskshareElement = document.getElementById("deskshare");
|
||||
if (deskshareElement == null) {
|
||||
|
||||
console.log("Starting deskshare applet.");
|
||||
var div = document.createElement("div");
|
||||
div.id = "deskshare";
|
||||
|
||||
div.innerHTML =
|
||||
"<applet code=\"org.bigbluebutton.deskshare.client.DeskShareApplet.class\"" +
|
||||
"id=\"DeskShareApplet\" width=\"100\" height=\"10\" archive=\"bbb-deskshare-applet-0.9.0.jar\">" +
|
||||
"<param name=\"ROOM\" value=\"" + roomNumber + "\"/>" +
|
||||
"<param name=\"IP\" value=\"" + IP + "\"/>" +
|
||||
"<param name=\"useTLS\" value=\"" + useTLS + "\"/>" +
|
||||
"<param name=\"PORT\" value=\"9123\"/>" +
|
||||
"<param name=\"SCALE\" value=\"0.8\"/>" +
|
||||
"<param name=\"FULL_SCREEN\" value=\"" + fullScreen + "\"/>" +
|
||||
"<param name=\"SVC2\" value=\"" + useSVC2 + "\"/>" +
|
||||
"<param name=\"JavaVersion\" value=\"1.7.0_51\"/>" +
|
||||
"<param name=\"permissions\" value=\"all-permissions\"/>" +
|
||||
"</applet>";
|
||||
document.body.appendChild(div);
|
||||
} else {
|
||||
console.log("Deskshare applet element already exists.");
|
||||
var div = document.getElementById("deskshare");
|
||||
if (div.parentNode) {
|
||||
// Just rewrite the applet tag to kick off the applet. We don't remove the applet tag
|
||||
// when desktop sharing is stopped to prevent Firefox (38.0.5) from asking for user permissions
|
||||
// again resulting in the page reloading. (ralam june 17, 2015)
|
||||
// https://code.google.com/p/bigbluebutton/issues/detail?id=1953
|
||||
div.innerHTML =
|
||||
"<applet code=\"org.bigbluebutton.deskshare.client.DeskShareApplet.class\"" +
|
||||
"id=\"DeskShareApplet\" width=\"100\" height=\"10\" archive=\"bbb-deskshare-applet-0.9.0.jar\">" +
|
||||
"<param name=\"ROOM\" value=\"" + roomNumber + "\"/>" +
|
||||
"<param name=\"IP\" value=\"" + IP + "\"/>" +
|
||||
"<param name=\"PORT\" value=\"9123\"/>" +
|
||||
"<param name=\"SCALE\" value=\"0.8\"/>" +
|
||||
"<param name=\"FULL_SCREEN\" value=\"" + fullScreen + "\"/>" +
|
||||
"<param name=\"SVC2\" value=\"" + useSVC2 + "\"/>" +
|
||||
"<param name=\"JavaVersion\" value=\"1.7.0_51\"/>" +
|
||||
"<param name=\"permissions\" value=\"all-permissions\"/>" +
|
||||
"</applet>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function removeFrame () {
|
||||
var div = document.getElementById("deskshare");
|
||||
if (div.parentNode) {
|
||||
// Need to set the innerHTML otherwise the applet will restart in IE.
|
||||
// see https://code.google.com/p/bigbluebutton/issues/detail?id=1776
|
||||
// Do NOT remove the applet tag as it makes Firefox (38.0.5) prompt for
|
||||
// permissions again resulting in the page reloading. (ralam june 17, 2015)
|
||||
// div.innerHTML = "";
|
||||
// div.parentNode.removeChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
function setScreenCoordinates(x, y) {
|
||||
document.DeskShareApplet.setScreenCoordinates(x,y);
|
||||
}
|
||||
|
||||
function stopApplet(){
|
||||
console.log("Stopping deskshare applet.");
|
||||
removeFrame();
|
||||
}
|
||||
|
||||
function appletStartupCallback() {
|
||||
BBB.javaAppletLaunched();
|
||||
}
|
||||
|
||||
function getHighestJavaVersion(javas) {
|
||||
var highestJava = javas[0];
|
||||
console.log("highestJava = [" + highestJava + "]");
|
||||
for (j = 0; j < javas.length; j++) {
|
||||
var java = javas[j];
|
||||
console.log("java[" + j + "]=[" + java + "]");
|
||||
var highest = highestJava.split(".");
|
||||
console.log(highest);
|
||||
var iter = java.split(".");
|
||||
console.log(iter);
|
||||
|
||||
if (parseInt(iter[0]) > parseInt(highest[0])) {
|
||||
highestJava = java;
|
||||
} else if (parseInt(iter[0]) == parseInt(highest[0]) && parseInt(iter[1]) > parseInt(highest[1])) {
|
||||
highestJava = java;
|
||||
console.log(highestJava);
|
||||
} else if (parseInt(iter[0]) == parseInt(highest[0]) && parseInt(iter[1]) == parseInt(highest[1])) {
|
||||
var iterMinor = parseInt((iter[2]).split("_")[1]);
|
||||
var highestMinor = parseInt((highest[2]).split("_")[1]);
|
||||
if (iterMinor > highestMinor) {
|
||||
highestJava = java;
|
||||
console.log(highestJava);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return highestJava;
|
||||
}
|
||||
|
||||
function getIcedTeaWebVersion() {
|
||||
for (i = 0; i < navigator.plugins.length; i++) {
|
||||
var matches;
|
||||
if (matches = navigator.plugins[i].name.match(/using IcedTea-Web ([0-9.]+)/)) {
|
||||
return matches[1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isJavaVersionOk(installedVersion, minVersion) {
|
||||
var required = minVersion.split(".");
|
||||
highest = installedVersion.split(".");
|
||||
if (parseInt(required[0]) > parseInt(highest[0])) {
|
||||
console.log("older major version=[" + installedVersion + "]");
|
||||
return {result: "JAVA_OLDER", version: installedVersion};
|
||||
} else if (parseInt(required[0]) == parseInt(highest[0]) && parseInt(required[1]) > parseInt(highest[1])) {
|
||||
console.log("older minor version=[" + installedVersion + "]");
|
||||
return {result: "JAVA_OLDER", version: installedVersion};
|
||||
} else if (parseInt(required[0]) == parseInt(highest[0]) && parseInt(required[1]) == parseInt(highest[1])) {
|
||||
var requiredMinor = parseInt((required[2]).split("_")[1]);
|
||||
var highestJavaMinor = parseInt((highest[2]).split("_")[1]);
|
||||
if (requiredMinor > highestJavaMinor) {
|
||||
console.log("older update version=[" + installedVersion + "]");
|
||||
return {result: "JAVA_OLDER", version: installedVersion};
|
||||
}
|
||||
}
|
||||
|
||||
return {result: "JAVA_OK"};
|
||||
}
|
||||
|
||||
function isIcedTeaVersionOkLinux(installedVersion, minVersion) {
|
||||
var required = minVersion.split(".");
|
||||
highest = installedVersion.split(".");
|
||||
if (parseInt(required[0]) > parseInt(highest[0])) {
|
||||
console.log("ice: older major version=[" + installedVersion + "]");
|
||||
return {result: "JAVA_OLDER", version: installedVersion};
|
||||
} else if (parseInt(required[0]) == parseInt(highest[0]) && parseInt(required[1]) > parseInt(highest[1])) {
|
||||
console.log("ice: older minor version=[" + installedVersion + "]");
|
||||
return {result: "JAVA_OLDER", version: installedVersion};
|
||||
}
|
||||
|
||||
return {result: "JAVA_OK"};
|
||||
}
|
||||
|
||||
function checkJavaVersion(minJavaVersion) {
|
||||
var javas = deployJava.getJREs();
|
||||
var highestJavaVersion = null;
|
||||
|
||||
if (javas == null || javas.length == 0) {
|
||||
if (javas == null) {
|
||||
return {result:"JAVA_NOT_DETECTED"};
|
||||
}
|
||||
|
||||
if (javas.length == 0) {
|
||||
return {result: "JAVA_NOT_INSTALLED"};
|
||||
}
|
||||
} else {
|
||||
var highestJavaVersion = getHighestJavaVersion(javas);
|
||||
var isOk = isJavaVersionOk(highestJavaVersion, minJavaVersion);
|
||||
if (isOk.result === "JAVA_OLDER") {
|
||||
highestJavaVersion = getIcedTeaWebVersion();
|
||||
return isIcedTeaVersionOkLinux(highestJavaVersion, "1.5.0");
|
||||
} else {
|
||||
return isOk;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
27
clients/flash/web-client/src/main/resources/lib/bbb_localization.js
Executable file
27
clients/flash/web-client/src/main/resources/lib/bbb_localization.js
Executable file
@ -0,0 +1,27 @@
|
||||
// Check locale
|
||||
var localeChain = "en_US";
|
||||
|
||||
if (navigator.language)
|
||||
localeChain = navigator.language;
|
||||
else if (navigator.browserLanguage)
|
||||
localeChain = navigator.browserLanguage;
|
||||
|
||||
if(/^([a-z]+)-([a-z]+)$/i.test(localeChain)){
|
||||
var matches = /^([a-z]+)-([a-z]+)$/i.exec(localeChain);
|
||||
localeChain = matches[1].toLowerCase() + "_" + matches[2].toUpperCase();
|
||||
}
|
||||
else if(/^en$/i.test(localeChain)){
|
||||
localeChain = "en_US";
|
||||
}
|
||||
else if(/^([a-z]+)$/i.test(localeChain)){
|
||||
var matches = /^([a-z]+)$/i.exec(localeChain);
|
||||
localeChain = matches[1].toLowerCase() + "_" + matches[1].toUpperCase();
|
||||
}
|
||||
else{
|
||||
localeChain = "en_US";
|
||||
}
|
||||
|
||||
function getLanguage(){
|
||||
return localeChain;
|
||||
}
|
||||
|
27
clients/flash/web-client/src/main/resources/lib/bbb_screenshare.js
Executable file
27
clients/flash/web-client/src/main/resources/lib/bbb_screenshare.js
Executable file
@ -0,0 +1,27 @@
|
||||
function startScreensharing(jnlp, meetingId, authToken, fullScreen)
|
||||
{
|
||||
console.log("Starting JSW [" + authToken + "]");
|
||||
var launchuri = jnlp + "?authToken=" + authToken + "&fullScreen=" + fullScreen + "&meetingId=" + meetingId;
|
||||
|
||||
$('<iframe id="iframe"><iframe/>').attr('src', launchuri).hide().appendTo('body');
|
||||
}
|
||||
|
||||
|
||||
function removeFrame () {
|
||||
var div = document.getElementById("deskshare");
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
|
||||
function setScreenCoordinates(x, y) {
|
||||
document.DeskShareApplet.setScreenCoordinates(x,y);
|
||||
}
|
||||
|
||||
function stopApplet(){
|
||||
document.DeskShareApplet.destroy();
|
||||
removeFrame();
|
||||
}
|
||||
|
||||
function checkForJava(){
|
||||
// if (navigator.javaEnabled() || window.navigator.javaEnabled())
|
||||
return 1;
|
||||
}
|
522
clients/flash/web-client/src/main/resources/lib/bbb_webrtc_bridge_sip.js
Executable file
522
clients/flash/web-client/src/main/resources/lib/bbb_webrtc_bridge_sip.js
Executable file
@ -0,0 +1,522 @@
|
||||
|
||||
var userID, callerIdName=null, conferenceVoiceBridge, userAgent=null, userMicMedia, userWebcamMedia, currentSession=null, callTimeout, callActive, callICEConnected, iceConnectedTimeout, callFailCounter, callPurposefullyEnded, uaConnected, transferTimeout, iceGatheringTimeout;
|
||||
var inEchoTest = true;
|
||||
|
||||
function webRTCCallback(message) {
|
||||
switch (message.status) {
|
||||
case 'failed':
|
||||
if (message.errorcode !== 1004) {
|
||||
message.cause = null;
|
||||
}
|
||||
BBB.webRTCCallFailed(inEchoTest, message.errorcode, message.cause);
|
||||
break;
|
||||
case 'ended':
|
||||
BBB.webRTCCallEnded(inEchoTest);
|
||||
break;
|
||||
case 'started':
|
||||
BBB.webRTCCallStarted(inEchoTest);
|
||||
break;
|
||||
case 'connecting':
|
||||
BBB.webRTCCallConnecting(inEchoTest);
|
||||
break;
|
||||
case 'waitingforice':
|
||||
BBB.webRTCCallWaitingForICE(inEchoTest);
|
||||
break;
|
||||
case 'transferring':
|
||||
BBB.webRTCCallTransferring(inEchoTest);
|
||||
break;
|
||||
case 'mediarequest':
|
||||
BBB.webRTCMediaRequest();
|
||||
break;
|
||||
case 'mediasuccess':
|
||||
BBB.webRTCMediaSuccess();
|
||||
break;
|
||||
case 'mediafail':
|
||||
BBB.webRTCMediaFail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function callIntoConference(voiceBridge, callback, isListenOnly) {
|
||||
// root of the call initiation process from the html5 client
|
||||
// Flash will not pass in the listen only field. For html5 it is optional. Assume NOT listen only if no state passed
|
||||
if (isListenOnly == null) {
|
||||
isListenOnly = false;
|
||||
}
|
||||
// reset callerIdName
|
||||
callerIdName = null;
|
||||
if (!callerIdName) {
|
||||
BBB.getMyUserInfo(function(userInfo) {
|
||||
console.log("User info callback [myUserID=" + userInfo.myUserID
|
||||
+ ",myUsername=" + userInfo.myUsername + ",myAvatarURL=" + userInfo.myAvatarURL
|
||||
+ ",myRole=" + userInfo.myRole + ",amIPresenter=" + userInfo.amIPresenter
|
||||
+ ",dialNumber=" + userInfo.dialNumber + ",voiceBridge=" + userInfo.voiceBridge
|
||||
+ ",isListenOnly=" + isListenOnly + "].");
|
||||
userID = userInfo.myUserID;
|
||||
callerIdName = userInfo.myUserID + "-bbbID-" + userInfo.myUsername;
|
||||
if (isListenOnly) {
|
||||
//prepend the callerIdName so it is recognized as a global audio user
|
||||
callerIdName = "GLOBAL_AUDIO_" + callerIdName;
|
||||
}
|
||||
conferenceVoiceBridge = userInfo.voiceBridge
|
||||
if (voiceBridge === "9196") {
|
||||
voiceBridge = voiceBridge + conferenceVoiceBridge;
|
||||
} else {
|
||||
voiceBridge = conferenceVoiceBridge;
|
||||
}
|
||||
console.log(callerIdName);
|
||||
webrtc_call(callerIdName, voiceBridge, callback, isListenOnly);
|
||||
});
|
||||
} else {
|
||||
if (voiceBridge === "9196") {
|
||||
voiceBridge = voiceBridge + conferenceVoiceBridge;
|
||||
} else {
|
||||
voiceBridge = conferenceVoiceBridge;
|
||||
}
|
||||
webrtc_call(callerIdName, voiceBridge, callback, isListenOnly);
|
||||
}
|
||||
}
|
||||
|
||||
function joinWebRTCVoiceConference() {
|
||||
console.log("Joining to the voice conference directly");
|
||||
inEchoTest = false;
|
||||
// set proper callbacks to previously created user agent
|
||||
if(userAgent) {
|
||||
setUserAgentListeners(webRTCCallback);
|
||||
}
|
||||
callIntoConference(conferenceVoiceBridge, webRTCCallback);
|
||||
}
|
||||
|
||||
function leaveWebRTCVoiceConference() {
|
||||
console.log("Leaving the voice conference");
|
||||
|
||||
webrtc_hangup();
|
||||
}
|
||||
|
||||
function startWebRTCAudioTest(){
|
||||
console.log("Joining the audio test first");
|
||||
inEchoTest = true;
|
||||
callIntoConference("9196", webRTCCallback);
|
||||
}
|
||||
|
||||
function stopWebRTCAudioTest(){
|
||||
console.log("Stopping webrtc audio test");
|
||||
|
||||
webrtc_hangup();
|
||||
}
|
||||
|
||||
function stopWebRTCAudioTestJoinConference(){
|
||||
console.log("Transferring from audio test to conference");
|
||||
|
||||
webRTCCallback({'status': 'transferring'});
|
||||
|
||||
transferTimeout = setTimeout( function() {
|
||||
console.log("Call transfer failed. No response after 3 seconds");
|
||||
webRTCCallback({'status': 'failed', 'errorcode': 1008});
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
BBB.listen("UserJoinedVoiceEvent", userJoinedVoiceHandler);
|
||||
|
||||
currentSession.dtmf(1);
|
||||
inEchoTest = false;
|
||||
}
|
||||
|
||||
function userJoinedVoiceHandler(event) {
|
||||
console.log("UserJoinedVoiceHandler - " + event);
|
||||
if (inEchoTest === false && userID === event.userID) {
|
||||
BBB.unlisten("UserJoinedVoiceEvent", userJoinedVoiceHandler);
|
||||
clearTimeout(transferTimeout);
|
||||
webRTCCallback({'status': 'started'});
|
||||
}
|
||||
}
|
||||
|
||||
function createUA(username, server, callback, makeCallFunc) {
|
||||
if (userAgent) {
|
||||
console.log("User agent already created");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Fetching STUN/TURN server info for user agent");
|
||||
|
||||
$.ajax({
|
||||
dataType: 'json',
|
||||
url: '/bigbluebutton/api/stuns'
|
||||
}).done(function(data) {
|
||||
var stunsConfig = {};
|
||||
stunsConfig['stunServers'] = ( data['stunServers'] ? data['stunServers'].map(function(data) {
|
||||
return data['url'];
|
||||
}) : [] );
|
||||
stunsConfig['turnServers'] = ( data['turnServers'] ? data['turnServers'].map(function(data) {
|
||||
return {
|
||||
'urls': data['url'],
|
||||
'username': data['username'],
|
||||
'password': data['password']
|
||||
};
|
||||
}) : [] );
|
||||
createUAWithStuns(username, server, callback, stunsConfig, makeCallFunc);
|
||||
}).fail(function(data, textStatus, errorThrown) {
|
||||
BBBLog.error("Could not fetch stun/turn servers", {error: textStatus, user: callerIdName, voiceBridge: conferenceVoiceBridge});
|
||||
callback({'status':'failed', 'errorcode': 1009});
|
||||
});
|
||||
}
|
||||
|
||||
function createUAWithStuns(username, server, callback, stunsConfig, makeCallFunc) {
|
||||
console.log("Creating new user agent");
|
||||
|
||||
/* VERY IMPORTANT
|
||||
* - You must escape the username because spaces will cause the connection to fail
|
||||
* - We are connecting to the websocket through an nginx redirect instead of directly to 5066
|
||||
*/
|
||||
var configuration = {
|
||||
uri: 'sip:' + encodeURIComponent(username) + '@' + server,
|
||||
wsServers: 'ws://' + server + '/ws',
|
||||
displayName: username,
|
||||
register: false,
|
||||
traceSip: true,
|
||||
autostart: false,
|
||||
userAgentString: "BigBlueButton",
|
||||
stunServers: stunsConfig['stunServers'],
|
||||
turnServers: stunsConfig['turnServers']
|
||||
};
|
||||
|
||||
uaConnected = false;
|
||||
|
||||
userAgent = new SIP.UA(configuration);
|
||||
setUserAgentListeners(callback, makeCallFunc);
|
||||
userAgent.start();
|
||||
};
|
||||
|
||||
function setUserAgentListeners(callback, makeCallFunc) {
|
||||
console.log("reseting UA callbacks");
|
||||
userAgent.off('connected');
|
||||
userAgent.on('connected', function() {
|
||||
uaConnected = true;
|
||||
makeCallFunc();
|
||||
});
|
||||
userAgent.off('disconnected');
|
||||
userAgent.on('disconnected', function() {
|
||||
if (userAgent) {
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
|
||||
if (uaConnected) {
|
||||
callback({'status':'failed', 'errorcode': 1001}); // WebSocket disconnected
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': 1002}); // Could not make a WebSocket connection
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function getUserMicMedia(getUserMicMediaSuccess, getUserMicMediaFailure) {
|
||||
if (userMicMedia == undefined) {
|
||||
if (SIP.WebRTC.isSupported()) {
|
||||
SIP.WebRTC.getUserMedia({audio:true, video:false}, getUserMicMediaSuccess, getUserMicMediaFailure);
|
||||
} else {
|
||||
console.log("getUserMicMedia: webrtc not supported");
|
||||
getUserMicMediaFailure("WebRTC is not supported");
|
||||
}
|
||||
} else {
|
||||
console.log("getUserMicMedia: mic already set");
|
||||
getUserMicMediaSuccess(userMicMedia);
|
||||
}
|
||||
};
|
||||
|
||||
function webrtc_call(username, voiceBridge, callback, isListenOnly) {
|
||||
if (!isWebRTCAvailable()) {
|
||||
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
|
||||
return;
|
||||
}
|
||||
if (isListenOnly == null) { // assume NOT listen only unless otherwise stated
|
||||
isListenOnly = false;
|
||||
}
|
||||
|
||||
var server = window.document.location.hostname;
|
||||
console.log("user " + username + " calling to " + voiceBridge);
|
||||
|
||||
var makeCallFunc = function() {
|
||||
// only make the call when both microphone and useragent have been created
|
||||
// for listen only, stating listen only is a viable substitute for acquiring user media control
|
||||
if ((isListenOnly||userMicMedia) && userAgent)
|
||||
make_call(username, voiceBridge, server, callback, false, isListenOnly);
|
||||
};
|
||||
|
||||
// Reset userAgent so we can successfully switch between listenOnly and listen+speak modes
|
||||
userAgent = null;
|
||||
if (!userAgent) {
|
||||
createUA(username, server, callback, makeCallFunc);
|
||||
}
|
||||
// if the user requests to proceed as listen only (does not require media) or media is already acquired,
|
||||
// proceed with making the call
|
||||
if (isListenOnly || userMicMedia !== undefined) {
|
||||
makeCallFunc();
|
||||
} else {
|
||||
callback({'status':'mediarequest'});
|
||||
getUserMicMedia(function(stream) {
|
||||
console.log("getUserMicMedia: success");
|
||||
userMicMedia = stream;
|
||||
callback({'status':'mediasuccess'});
|
||||
makeCallFunc();
|
||||
}, function(e) {
|
||||
console.error("getUserMicMedia: failure - " + e);
|
||||
callback({'status':'mediafail', 'cause': e});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function make_call(username, voiceBridge, server, callback, recall, isListenOnly) {
|
||||
if (isListenOnly == null) {
|
||||
isListenOnly = false;
|
||||
}
|
||||
|
||||
if (userAgent == null) {
|
||||
console.log("userAgent is still null. Delaying call");
|
||||
var callDelayTimeout = setTimeout( function() {
|
||||
make_call(username, voiceBridge, server, callback, recall, isListenOnly);
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userAgent.isConnected()) {
|
||||
console.log("Trying to make call, but UserAgent hasn't connected yet. Delaying call");
|
||||
userAgent.once('connected', function() {
|
||||
console.log("UserAgent has now connected, retrying the call");
|
||||
make_call(username, voiceBridge, server, callback, recall, isListenOnly);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentSession) {
|
||||
console.log('Active call detected ignoring second make_call');
|
||||
return;
|
||||
}
|
||||
|
||||
// Make an audio/video call:
|
||||
console.log("Setting options.. ");
|
||||
|
||||
var options = {};
|
||||
if (isListenOnly) {
|
||||
// create necessary options for a listen only stream
|
||||
var stream = null;
|
||||
// handle the web browser
|
||||
// create a stream object through the browser separated from user media
|
||||
if (typeof webkitMediaStream !== 'undefined') {
|
||||
// Google Chrome
|
||||
stream = new webkitMediaStream;
|
||||
} else {
|
||||
// Firefox
|
||||
audioContext = new window.AudioContext;
|
||||
stream = audioContext.createMediaStreamDestination().stream;
|
||||
}
|
||||
|
||||
options = {
|
||||
media: {
|
||||
stream: stream, // use the stream created above
|
||||
render: {
|
||||
remote: {
|
||||
// select an element to render the incoming stream data
|
||||
audio: document.getElementById('remote-media')
|
||||
}
|
||||
}
|
||||
},
|
||||
// a list of our RTC Connection constraints
|
||||
RTCConstraints: {
|
||||
// our constraints are mandatory. We must received audio and must not receive audio
|
||||
mandatory: {
|
||||
OfferToReceiveAudio: true,
|
||||
OfferToReceiveVideo: false
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
media: {
|
||||
stream: userMicMedia,
|
||||
render: {
|
||||
remote: {
|
||||
audio: document.getElementById('remote-media')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
callTimeout = setTimeout(function() {
|
||||
console.log('Ten seconds without updates sending timeout code');
|
||||
callback({'status':'failed', 'errorcode': 1006}); // Failure on call
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
callActive = false;
|
||||
callICEConnected = false;
|
||||
callPurposefullyEnded = false;
|
||||
callFailCounter = 0;
|
||||
console.log("Calling to " + voiceBridge + "....");
|
||||
currentSession = userAgent.invite('sip:' + voiceBridge + '@' + server, options);
|
||||
|
||||
// Only send the callback if it's the first try
|
||||
if (recall === false) {
|
||||
console.log('call connecting');
|
||||
callback({'status':'connecting'});
|
||||
} else {
|
||||
console.log('call connecting again');
|
||||
}
|
||||
|
||||
iceGatheringTimeout = setTimeout(function() {
|
||||
console.log('Thirty seconds without ICE gathering finishing');
|
||||
callback({'status':'failed', 'errorcode': 1011}); // ICE Gathering Failed
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
currentSession.mediaHandler.on('iceComplete', function() {
|
||||
clearTimeout(iceGatheringTimeout);
|
||||
});
|
||||
|
||||
// The connecting event fires before the listener can be added
|
||||
currentSession.on('connecting', function(){
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('progress', function(response){
|
||||
console.log('call progress: ' + response);
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('failed', function(response, cause){
|
||||
console.log('call failed with cause: '+ cause);
|
||||
|
||||
if (currentSession) {
|
||||
if (callActive === false) {
|
||||
callback({'status':'failed', 'errorcode': 1004, 'cause': cause}); // Failure on call
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
} else {
|
||||
callActive = false;
|
||||
//currentSession.bye();
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
userAgent.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.on('bye', function(request){
|
||||
callActive = false;
|
||||
|
||||
if (currentSession) {
|
||||
console.log('call ended ' + currentSession.endTime);
|
||||
|
||||
if (callPurposefullyEnded === true) {
|
||||
callback({'status':'ended'});
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': 1005}); // Call ended unexpectedly
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
currentSession = null;
|
||||
} else {
|
||||
console.log('bye event already received');
|
||||
}
|
||||
});
|
||||
currentSession.on('accepted', function(data){
|
||||
callActive = true;
|
||||
console.log('BigBlueButton call accepted');
|
||||
|
||||
if (callICEConnected === true) {
|
||||
callback({'status':'started'});
|
||||
} else {
|
||||
callback({'status':'waitingforice'});
|
||||
console.log('Waiting for ICE negotiation');
|
||||
iceConnectedTimeout = setTimeout(function() {
|
||||
console.log('60 seconds without ICE finishing');
|
||||
callback({'status':'failed', 'errorcode': 1010}); // ICE negotiation timeout
|
||||
currentSession = null;
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
currentSession.mediaHandler.on('iceFailed', function() {
|
||||
console.log('received ice negotiation failed');
|
||||
callback({'status':'failed', 'errorcode': 1007}); // Failure on call
|
||||
currentSession = null;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (userAgent != null) {
|
||||
var userAgentTemp = userAgent;
|
||||
userAgent = null;
|
||||
userAgentTemp.stop();
|
||||
}
|
||||
|
||||
clearTimeout(callTimeout);
|
||||
});
|
||||
|
||||
// Some browsers use status of 'connected', others use 'completed', and a couple use both
|
||||
|
||||
currentSession.mediaHandler.on('iceConnected', function() {
|
||||
console.log('Received ICE status changed to connected');
|
||||
if (callICEConnected === false) {
|
||||
callICEConnected = true;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (callActive === true) {
|
||||
callback({'status':'started'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
});
|
||||
|
||||
currentSession.mediaHandler.on('iceCompleted', function() {
|
||||
console.log('Received ICE status changed to completed');
|
||||
if (callICEConnected === false) {
|
||||
callICEConnected = true;
|
||||
clearTimeout(iceConnectedTimeout);
|
||||
if (callActive === true) {
|
||||
callback({'status':'started'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function webrtc_hangup(callback) {
|
||||
callPurposefullyEnded = true;
|
||||
|
||||
console.log("Hanging up current session");
|
||||
if (callback) {
|
||||
currentSession.on('bye', callback);
|
||||
}
|
||||
currentSession.bye();
|
||||
}
|
||||
|
||||
function isWebRTCAvailable() {
|
||||
return SIP.WebRTC.isSupported();
|
||||
}
|
||||
|
||||
function getCallStatus() {
|
||||
return currentSession;
|
||||
}
|
28
clients/flash/web-client/src/main/resources/lib/bbblogger.js
Executable file
28
clients/flash/web-client/src/main/resources/lib/bbblogger.js
Executable file
@ -0,0 +1,28 @@
|
||||
|
||||
(function(window, undefined) {
|
||||
|
||||
var BBBLog = {};
|
||||
|
||||
BBBLog.critical = function (message, data) {
|
||||
console.log(message, JSON.stringify(data));
|
||||
}
|
||||
|
||||
BBBLog.error = function (message, data) {
|
||||
console.log(message, JSON.stringify(data));
|
||||
}
|
||||
|
||||
BBBLog.warning = function (message, data) {
|
||||
console.log(message, JSON.stringify(data));
|
||||
}
|
||||
|
||||
BBBLog.info = function (message, data) {
|
||||
console.log(message, JSON.stringify(data));
|
||||
}
|
||||
|
||||
BBBLog.debug = function (message, data) {
|
||||
console.log(message, JSON.stringify(data));
|
||||
}
|
||||
|
||||
window.BBBLog = BBBLog;
|
||||
})(this);
|
||||
|
26
clients/flash/web-client/src/main/resources/lib/bigbluebutton.js
Executable file
26
clients/flash/web-client/src/main/resources/lib/bigbluebutton.js
Executable file
@ -0,0 +1,26 @@
|
||||
$(function () {
|
||||
setTimeout(function(){
|
||||
$('#BigBlueButton').focus();
|
||||
},1000);
|
||||
});
|
||||
|
||||
function startFlashFocus() {
|
||||
f = $('#BigBlueButton')[0]
|
||||
f.tabIndex = 0;
|
||||
f.focus();
|
||||
}
|
||||
|
||||
function stopFlashFocus() {
|
||||
$('#enterFlash')[0].focus();
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/5916900/detect-version-of-browser
|
||||
navigator.sayswho= (function(){
|
||||
var ua= navigator.userAgent,
|
||||
N= navigator.appName,
|
||||
tem,
|
||||
M= ua.match(/(opera|chrome|safari|firefox|msie|trident)\/?\s*([\d\.]+)/i) || [];
|
||||
M= M[2]? [M[1], M[2]]:[N, navigator.appVersion, '-?'];
|
||||
if(M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
|
||||
return M;
|
||||
})();
|
2
clients/flash/web-client/src/main/resources/lib/deployJava.js
Executable file
2
clients/flash/web-client/src/main/resources/lib/deployJava.js
Executable file
File diff suppressed because one or more lines are too long
103
clients/flash/web-client/src/main/resources/lib/getScreenId.js
Executable file
103
clients/flash/web-client/src/main/resources/lib/getScreenId.js
Executable file
@ -0,0 +1,103 @@
|
||||
// Last time updated at Sep 07, 2014, 08:32:23
|
||||
|
||||
// Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js
|
||||
|
||||
// Muaz Khan - www.MuazKhan.com
|
||||
// MIT License - www.WebRTC-Experiment.com/licence
|
||||
// Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/getScreenId.js
|
||||
|
||||
// ______________
|
||||
// getScreenId.js
|
||||
|
||||
/*
|
||||
getScreenId(function (error, sourceId, screen_constraints) {
|
||||
// error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome'
|
||||
// sourceId == null || 'string' || 'firefox'
|
||||
|
||||
if(sourceId == 'firefox') {
|
||||
navigator.mozGetUserMedia(screen_constraints, onSuccess, onFailure);
|
||||
}
|
||||
else navigator.webkitGetUserMedia(screen_constraints, onSuccess, onFailure);
|
||||
});
|
||||
*/
|
||||
|
||||
(function() {
|
||||
window.getScreenId = function(callback) {
|
||||
// for Firefox:
|
||||
// sourceId == 'firefox'
|
||||
// screen_constraints = {...}
|
||||
if (!!navigator.mozGetUserMedia) {
|
||||
callback(null, 'firefox', {
|
||||
video: {
|
||||
mozMediaSource: 'window',
|
||||
mediaSource: 'window'
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
postMessage();
|
||||
|
||||
window.addEventListener('message', onIFrameCallback);
|
||||
|
||||
function onIFrameCallback(event) {
|
||||
if (!event.data) return;
|
||||
|
||||
if (event.data.chromeMediaSourceId) {
|
||||
if (event.data.chromeMediaSourceId === 'PermissionDeniedError') {
|
||||
callback('permission-denied');
|
||||
} else callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId));
|
||||
}
|
||||
|
||||
if (event.data.chromeExtensionStatus) {
|
||||
callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus));
|
||||
}
|
||||
|
||||
// this event listener is no more needed
|
||||
window.removeEventListener('message', onIFrameCallback);
|
||||
}
|
||||
};
|
||||
|
||||
function getScreenConstraints(error, sourceId) {
|
||||
var screen_constraints = {
|
||||
audio: false,
|
||||
video: {
|
||||
mandatory: {
|
||||
chromeMediaSource: error ? 'screen' : 'desktop',
|
||||
maxWidth: window.screen.width > 1920 ? window.screen.width : 1920,
|
||||
maxHeight: window.screen.height > 1080 ? window.screen.height : 1080
|
||||
},
|
||||
optional: []
|
||||
}
|
||||
};
|
||||
console.log("____in getScreenConstraints and error=" + error + " and sourceId=" + sourceId +
|
||||
" and chromeMediaSource = " + screen_constraints.video.mandatory.chromeMediaSource);
|
||||
|
||||
if (sourceId) {
|
||||
screen_constraints.video.mandatory.chromeMediaSourceId = sourceId;
|
||||
}
|
||||
|
||||
return screen_constraints;
|
||||
}
|
||||
|
||||
function postMessage() {
|
||||
console.log("___in postMessage and iframe isLoaded=" + iframe.isLoaded);
|
||||
|
||||
if (!iframe.isLoaded) {
|
||||
setTimeout(postMessage, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
iframe.contentWindow.postMessage({
|
||||
captureSourceId: true
|
||||
}, '*');
|
||||
}
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.onload = function() {
|
||||
iframe.isLoaded = true;
|
||||
};
|
||||
iframe.src = 'https://www.webrtc-experiment.com/getSourceId/';
|
||||
iframe.style.display = 'none';
|
||||
(document.body || document.documentElement).appendChild(iframe);
|
||||
})();
|
16
clients/flash/web-client/src/main/resources/lib/jquery-1.5.1.min.js
vendored
Executable file
16
clients/flash/web-client/src/main/resources/lib/jquery-1.5.1.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
4
clients/flash/web-client/src/main/resources/lib/jquery-2.1.1.min.js
vendored
Executable file
4
clients/flash/web-client/src/main/resources/lib/jquery-2.1.1.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1267
clients/flash/web-client/src/main/resources/lib/jquery.FSRTC.js
Executable file
1267
clients/flash/web-client/src/main/resources/lib/jquery.FSRTC.js
Executable file
File diff suppressed because it is too large
Load Diff
90
clients/flash/web-client/src/main/resources/lib/jquery.cookie.js
Executable file
90
clients/flash/web-client/src/main/resources/lib/jquery.cookie.js
Executable file
@ -0,0 +1,90 @@
|
||||
/*!
|
||||
* jQuery Cookie Plugin v1.3.1
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2013 Klaus Hartl
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function ($, document, undefined) {
|
||||
|
||||
var pluses = /\+/g;
|
||||
|
||||
function raw(s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
function decoded(s) {
|
||||
return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
|
||||
}
|
||||
|
||||
function unRfc2068(value) {
|
||||
if (value.indexOf('"') === 0) {
|
||||
// This is a quoted cookie as according to RFC2068, unescape
|
||||
value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function fromJSON(value) {
|
||||
return config.json ? JSON.parse(value) : value;
|
||||
}
|
||||
|
||||
var config = $.cookie = function (key, value, options) {
|
||||
|
||||
// write
|
||||
if (value !== undefined) {
|
||||
options = $.extend({}, config.defaults, options);
|
||||
|
||||
if (value === null) {
|
||||
options.expires = -1;
|
||||
}
|
||||
|
||||
if (typeof options.expires === 'number') {
|
||||
var days = options.expires, t = options.expires = new Date();
|
||||
t.setDate(t.getDate() + days);
|
||||
}
|
||||
|
||||
value = config.json ? JSON.stringify(value) : String(value);
|
||||
|
||||
return (document.cookie = [
|
||||
encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
|
||||
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||
options.path ? '; path=' + options.path : '',
|
||||
options.domain ? '; domain=' + options.domain : '',
|
||||
options.secure ? '; secure' : ''
|
||||
].join(''));
|
||||
}
|
||||
|
||||
// read
|
||||
var decode = config.raw ? raw : decoded;
|
||||
var cookies = document.cookie.split('; ');
|
||||
var result = key ? null : {};
|
||||
for (var i = 0, l = cookies.length; i < l; i++) {
|
||||
var parts = cookies[i].split('=');
|
||||
var name = decode(parts.shift());
|
||||
var cookie = decode(parts.join('='));
|
||||
|
||||
if (key && key === name) {
|
||||
result = fromJSON(cookie);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
result[name] = fromJSON(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
config.defaults = {};
|
||||
|
||||
$.removeCookie = function (key, options) {
|
||||
if ($.cookie(key) !== null) {
|
||||
$.cookie(key, null, options);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
})(jQuery, document);
|
155
clients/flash/web-client/src/main/resources/lib/jquery.dataTables.min.js
vendored
Executable file
155
clients/flash/web-client/src/main/resources/lib/jquery.dataTables.min.js
vendored
Executable file
@ -0,0 +1,155 @@
|
||||
/*! DataTables 1.10.1
|
||||
* ©2008-2014 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
(function(za,O,l){var N=function(h){function T(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),d[c]=e,"o"===b[1]&&T(a[e])});a._hungarianMap=d}function G(a,b,c){a._hungarianMap||T(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==l&&(c||b[d]===l))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),G(a[d],b[d],c)):b[d]=b[e]})}function N(a){var b=p.defaults.oLanguage,c=a.sZeroRecords;
|
||||
!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&D(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&D(a,a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&cb(a)}function db(a){w(a,"ordering","bSort");w(a,"orderMulti","bSortMulti");w(a,"orderClasses","bSortClasses");w(a,"orderCellsTop","bSortCellsTop");w(a,"order","aaSorting");w(a,"orderFixed","aaSortingFixed");w(a,"paging","bPaginate");
|
||||
w(a,"pagingType","sPaginationType");w(a,"pageLength","iDisplayLength");w(a,"searching","bFilter");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&G(p.models.oSearch,a[b])}function eb(a){w(a,"orderable","bSortable");w(a,"orderData","aDataSort");w(a,"orderSequence","asSorting");w(a,"orderDataType","sortDataType")}function fb(a){var a=a.oBrowser,b=h("<div/>").css({position:"absolute",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,width:100,
|
||||
overflow:"scroll"}).append(h('<div class="test"/>').css({width:"100%",height:10}))).appendTo("body"),c=b.find(".test");a.bScrollOversize=100===c[0].offsetWidth;a.bScrollbarLeft=1!==c.offset().left;b.remove()}function gb(a,b,c,d,e,f){var g,j=!1;c!==l&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&&(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Aa(a,b){var c=p.defaults.column,d=a.aoColumns.length,c=h.extend({},p.models.oColumn,c,{nTh:b?b:O.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:
|
||||
"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},p.models.oSearch,c[d]);fa(a,d,null)}function fa(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==l&&null!==c&&(eb(c),G(p.defaults.column,c),c.mDataProp!==l&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&
|
||||
!c.sClass&&(c.sClass=c.className),h.extend(b,c),D(b,c,"sWidth","sWidthOrig"),"number"===typeof c.iDataSort&&(b.aDataSort=[c.iDataSort]),D(b,c,"aDataSort"));var g=b.mData,j=U(g),i=b.mRender?U(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b.fnGetData=function(a,b,c){var d=j(a,b,l,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return Ba(g)(a,b,c)};a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));
|
||||
a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function V(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ca(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=
|
||||
a.oScroll;(""!==b.sY||""!==b.sX)&&W(a);u(a,null,"column-sizing",[a])}function ga(a,b){var c=X(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function Y(a,b){var c=X(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function Z(a){return X(a,"bVisible").length}function X(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Da(a){var b=a.aoColumns,c=a.aoData,d=p.ext.type.detect,e,f,g,j,i,h,m,n,k;e=0;for(f=b.length;e<f;e++)if(m=b[e],k=[],!m.sType&&m._sManualType)m.sType=
|
||||
m._sManualType;else if(!m.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h&&!(k[i]===l&&(k[i]=A(a,i,e,"type")),n=d[g](k[i],a),!n||"html"===n);i++);if(n){m.sType=n;break}}m.sType||(m.sType="string")}}function hb(a,b,c,d){var e,f,g,j,i,o,m=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){o=b[e];var n=o.targets!==l?o.targets:o.aTargets;h.isArray(n)||(n=[n]);f=0;for(g=n.length;f<g;f++)if("number"===typeof n[f]&&0<=n[f]){for(;m.length<=n[f];)Aa(a);d(n[f],o)}else if("number"===typeof n[f]&&0>n[f])d(m.length+
|
||||
n[f],o);else if("string"===typeof n[f]){j=0;for(i=m.length;j<i;j++)("_all"==n[f]||h(m[j].nTh).hasClass(n[f]))&&d(j,o)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function I(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},p.models.oRow,{src:c?"dom":"data"});f._aData=b;a.aoData.push(f);for(var b=a.aoColumns,f=0,g=b.length;f<g;f++)c&&Ea(a,e,f,A(a,e,f)),b[f].sType=null;a.aiDisplayMaster.push(e);(c||!a.oFeatures.bDeferRender)&&Fa(a,e,c,d);return e}function ha(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,
|
||||
e){c=ia(a,e);return I(a,c.data,e,c.cells)})}function A(a,b,c,d){var e=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,c=f.fnGetData(g,d,{settings:a,row:b,col:c});if(c===l)return a.iDrawError!=e&&null===j&&(P(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b,4),a.iDrawError=e),j;if((c===g||null===c)&&null!==j)c=j;else if("function"===typeof c)return c.call(g);return null===c&&"display"==d?"":c}function Ea(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,
|
||||
d,{settings:a,row:b,col:c})}function Ga(a){return h.map(a.match(/(\\.|[^\.])+/g),function(a){return a.replace(/\\./g,".")})}function U(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=U(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==l?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,
|
||||
j;if(""!==f){j=Ga(f);for(var i=0,h=j.length;i<h;i++){f=j[i].match($);g=j[i].match(Q);if(f){j[i]=j[i].replace($,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");i=0;for(h=a.length;i<h;i++)g.push(c(a[i],b,j));a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(Q,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===l)return l;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function Ba(a){if(h.isPlainObject(a))return Ba(a._);
|
||||
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ga(e),f;f=e[e.length-1];for(var g,j,i=0,h=e.length-1;i<h;i++){g=e[i].match($);j=e[i].match(Q);if(g){e[i]=e[i].replace($,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");j=0;for(h=d.length;j<h;j++)f={},b(f,d[j],g),a[e[i]].push(f);return}j&&(e[i]=e[i].replace(Q,""),a=a[e[i]](d));if(null===
|
||||
a[e[i]]||a[e[i]]===l)a[e[i]]={};a=a[e[i]]}if(f.match(Q))a[f.replace(Q,"")](d);else a[f.replace($,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ha(a){return C(a.aoData,"_aData")}function ja(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0}function ka(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===l&&a.splice(d,1)}function la(a,b,c,d){var e=a.aoData[b],f;if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=
|
||||
ia(a,e).data;else{var g=e.anCells,j;if(g){c=0;for(f=g.length;c<f;c++){for(j=g[c];j.childNodes.length;)j.removeChild(j.firstChild);g[c].innerHTML=A(a,b,c,"display")}}}e._aSortData=null;e._aFilterData=null;a=a.aoColumns;if(d!==l)a[d].sType=null;else{c=0;for(f=a.length;c<f;c++)a[c].sType=null}Ia(e)}function ia(a,b){var c=[],d=[],e=b.firstChild,f,g,j,i=0,o,m=a.aoColumns,n=function(a,b,c){"string"===typeof a&&(b=a.indexOf("@"),-1!==b&&(a=a.substring(b+1),j["@"+a]=c.getAttribute(a)))},k=function(a){g=m[i];
|
||||
o=h.trim(a.innerHTML);g&&g._bAttrSrc?(j={display:o},n(g.mData.sort,j,a),n(g.mData.type,j,a),n(g.mData.filter,j,a),c.push(j)):c.push(o);i++};if(e)for(;e;){f=e.nodeName.toUpperCase();if("TD"==f||"TH"==f)k(e),d.push(e);e=e.nextSibling}else{d=b.anCells;e=0;for(f=d.length;e<f;e++)k(d[e])}return{data:c,cells:d}}function Fa(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,h,m,n;if(null===e.nTr){j=c||O.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;Ia(e);m=0;for(n=a.aoColumns.length;m<n;m++){h=a.aoColumns[m];
|
||||
i=c?d[m]:O.createElement(h.sCellType);g.push(i);if(!c||h.mRender||h.mData!==m)i.innerHTML=A(a,b,m,"display");h.sClass&&(i.className+=" "+h.sClass);h.bVisible&&!c?j.appendChild(i):!h.bVisible&&c&&i.parentNode.removeChild(i);h.fnCreatedCell&&h.fnCreatedCell.call(a.oInstance,i,A(a,b,m),f,b,m)}u(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function Ia(a){var b=a.nTr,c=a._aData;if(b){c.DT_RowId&&(b.id=c.DT_RowId);if(c.DT_RowClass){var d=c.DT_RowClass.split(" ");a.__rowc=a.__rowc?
|
||||
Ja(a.__rowc.concat(d)):d;h(b).removeClass(a.__rowc.join(" ")).addClass(c.DT_RowClass)}c.DT_RowData&&h(b).data(c.DT_RowData)}}function ib(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===h("th, td",g).length,o=a.oClasses,m=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=m.length;b<c;b++)f=m[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Ka(a,f.nTh,b))),f.sTitle!=d.html()&&
|
||||
d.html(f.sTitle),La(a,"header")(a,d,f,o);i&&aa(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(o.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(o.sFooterTH);if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=m[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ba(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,o;if(b){c===l&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&
|
||||
!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(o=i=1,j[d][f]===l){a.appendChild(g[d][f].cell);for(j[d][f]=1;g[d+i]!==l&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+o]!==l&&g[d][f].cell==g[d][f+o].cell;){for(c=0;c<i;c++)j[d+c][f+o]=1;o++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",o)}}}}function K(a){var b=u(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))B(a,!1);else{var b=
|
||||
[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==z(a),i=a.aiDisplay;a.bDrawing=!0;g!==l&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,o=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,B(a,!1);else if(j){if(!a.bDestroying&&!jb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:o;for(j=j?0:g;j<f;j++){var m=i[j],n=a.aoData[m];null===n.nTr&&Fa(a,m);m=n.nTr;if(0!==e){var k=d[c%e];n._sRowStripe!=
|
||||
k&&(h(m).removeClass(n._sRowStripe).addClass(k),n._sRowStripe=k)}u(a,"aoRowCallback",null,[m,n._aData,c,j]);b.push(m);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==z(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:Z(a),"class":a.oClasses.sRowEmpty}).html(c))[0];u(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ha(a),g,o,i]);u(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],
|
||||
Ha(a),g,o,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));u(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function L(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&kb(a);d?ca(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;K(a);a._drawHold=!1}function lb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});
|
||||
a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,o,m,n,k=0;k<f.length;k++){g=null;j=f[k];if("<"==j){i=h("<div/>")[0];o=f[k+1];if("'"==o||'"'==o){m="";for(n=2;f[k+n]!=o;)m+=f[k+n],n++;"H"==m?m=b.sJUIHeader:"F"==m&&(m=b.sJUIFooter);-1!=m.indexOf(".")?(o=m.split("."),i.id=o[0].substr(1,o[0].length-1),i.className=o[1]):"#"==m.charAt(0)?i.id=m.substr(1,m.length-1):i.className=m;k+=n}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==
|
||||
j&&d.bPaginate&&d.bLengthChange)g=mb(a);else if("f"==j&&d.bFilter)g=nb(a);else if("r"==j&&d.bProcessing)g=ob(a);else if("t"==j)g=pb(a);else if("i"==j&&d.bInfo)g=qb(a);else if("p"==j&&d.bPaginate)g=rb(a);else if(0!==p.ext.feature.length){i=p.ext.feature;n=0;for(o=i.length;n<o;n++)if(j==i[n].cFeature){g=i[n].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e)}function aa(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,o,m,n,k;a.splice(0,a.length);f=0;for(i=c.length;f<
|
||||
i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){m=1*e.getAttribute("colspan");n=1*e.getAttribute("rowspan");m=!m||0===m||1===m?1:m;n=!n||0===n||1===n?1:n;g=0;for(j=a[f];j[g];)g++;o=g;k=1===m?!0:!1;for(j=0;j<m;j++)for(g=0;g<n;g++)a[f+g][o+j]={cell:e,unique:k},a[f+g].nTr=d}e=e.nextSibling}}}function ma(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],aa(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<
|
||||
g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function na(a,b,c){u(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance;if(h.isPlainObject(g)&&g.data){f=g.data;var i=h.isFunction(f)?f(b):f,b=h.isFunction(f)&&i?i:h.extend(!0,b,i);delete g.data}i={data:b,success:function(b){var d=b.error||b.sError;
|
||||
d&&a.oApi._fnLog(a,0,d);a.json=b;u(a,null,"xhr",[a,b]);c(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=a.oApi._fnLog;"parsererror"==c?d(a,0,"Invalid JSON response",1):4===b.readyState&&d(a,0,"Ajax error",7);B(a,!1)}};a.oAjaxData=b;u(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),c,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(i,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,
|
||||
b,c,a):(a.jqXHR=h.ajax(h.extend(i,g)),g.data=f)}function jb(a){return a.bAjaxDataGet?(a.iDraw++,B(a,!0),na(a,sb(a),function(b){tb(a,b)}),!1):!0}function sb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,o,m,n=R(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var k=function(a,b){j.push({name:a,value:b})};k("sEcho",a.iDraw);k("iColumns",c);k("sColumns",C(b,"sName").join(","));k("iDisplayStart",g);k("iDisplayLength",i);var l={draw:a.iDraw,
|
||||
columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)o=b[g],m=f[g],i="function"==typeof o.mData?"function":o.mData,l.columns.push({data:i,name:o.sName,searchable:o.bSearchable,orderable:o.bSortable,search:{value:m.sSearch,regex:m.bRegex}}),k("mDataProp_"+g,i),d.bFilter&&(k("sSearch_"+g,m.sSearch),k("bRegex_"+g,m.bRegex),k("bSearchable_"+g,o.bSearchable)),d.bSort&&k("bSortable_"+g,o.bSortable);d.bFilter&&(k("sSearch",e.sSearch),k("bRegex",e.bRegex));d.bSort&&
|
||||
(h.each(n,function(a,b){l.order.push({column:b.col,dir:b.dir});k("iSortCol_"+a,b.col);k("sSortDir_"+a,b.dir)}),k("iSortingCols",n.length));b=p.ext.legacy.ajax;return null===b?a.sAjaxSource?j:l:b?j:l}function tb(a,b){var c=b.sEcho!==l?b.sEcho:b.draw,d=b.iTotalRecords!==l?b.iTotalRecords:b.recordsTotal,e=b.iTotalDisplayRecords!==l?b.iTotalDisplayRecords:b.recordsFiltered;if(c){if(1*c<a.iDraw)return;a.iDraw=1*c}ja(a);a._iRecordsTotal=parseInt(d,10);a._iRecordsDisplay=parseInt(e,10);c=oa(a,b);d=0;for(e=
|
||||
c.length;d<e;d++)I(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;K(a);a._bInitComplete||pa(a,b);a.bAjaxDataGet=!0;B(a,!1)}function oa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==l?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?U(c)(b):b}function nb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",
|
||||
{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?"":this.value;b!=e.sSearch&&(ca(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,K(a))},i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT","ssp"===z(a)?Ma(f,400):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",
|
||||
function(b,c){if(a===c)try{i[0]!==O.activeElement&&i.val(e.sSearch)}catch(d){}});return b[0]}function ca(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Da(a);if("ssp"!=z(a)){ub(a,b.sSearch,c,b.bEscapeRegex!==l?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)vb(a,e[b].sSearch,b,e[b].bEscapeRegex!==l?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);
|
||||
wb(a)}else f(b);a.bFiltered=!0;u(a,null,"search",[a])}function wb(a){for(var b=p.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,h=c.length;i<h;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;c.push.apply(c,j)}}function vb(a,b,c,d,e,f){if(""!==b)for(var g=a.aiDisplay,d=Na(b,d,e,f),e=g.length-1;0<=e;e--)b=a.aoData[g[e]]._aFilterData[c],d.test(b)||g.splice(e,1)}function ub(a,b,c,d,e,f){var d=Na(b,d,e,f),e=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,
|
||||
g;0!==p.ext.search.length&&(c=!0);g=xb(a);if(0>=b.length)a.aiDisplay=f.slice();else{if(g||c||e.length>b.length||0!==b.indexOf(e)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)d.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Na(a,b,c,d){a=b?a:Oa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||"",function(a){return'"'===a.charAt(0)?a.match(/^"(.*)"$/)[1]:a}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function Oa(a){return a.replace(Vb,"\\$1")}function xb(a){var b=
|
||||
a.aoColumns,c,d,e,f,g,j,i,h,m=p.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)if(c=b[e],c.bSearchable?(i=A(a,d,e,"filter"),i=m[c.sType]?m[c.sType](i):null!==i?i:""):i="",i)i.indexOf&&-1!==i.indexOf("&")&&(qa.innerHTML=i,i=Wb?qa.textContent:qa.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function yb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,
|
||||
caseInsensitive:a.bCaseInsensitive}}function zb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function qb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Ab,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Ab(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+
|
||||
1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Bb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Bb(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,
|
||||
f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ra(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;if(a.bInitialised){lb(a);ib(a);ba(a,a.aoHeader);ba(a,a.aoFooter);B(a,!0);c.bAutoWidth&&Ca(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=s(f.sWidth));L(a);e=z(a);"ssp"!=e&&("ajax"==e?na(a,[],function(c){var f=oa(a,c);for(b=0;b<f.length;b++)I(a,f[b]);a.iInitDisplayStart=d;L(a);B(a,!1);pa(a,c)},a):(B(a,!1),
|
||||
pa(a)))}else setTimeout(function(){ra(a)},200)}function pa(a,b){a._bInitComplete=!0;b&&V(a);u(a,"aoInitComplete","init",[a,b])}function Pa(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Qa(a);u(a,null,"length",[a,c])}function mb(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option(d[g],f[g]);var i=h("<div><label/></div>").addClass(b.sLength);
|
||||
a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Pa(a,h(this).val());K(a)});h(a.nTable).bind("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function rb(a){var b=a.sPaginationType,c=p.ext.pager[b],d="function"===typeof c,e=function(a){K(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+
|
||||
"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),m=-1===i,b=m?0:Math.ceil(b/i),i=m?1:Math.ceil(h/i),h=c(b,i),n,m=0;for(n=f.p.length;m<n;m++)La(a,"pageButton")(a,f.p[m],m,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Ra(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==
|
||||
b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:P(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(u(a,null,"page",[a]),c&&K(a));return b}function ob(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function B(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");u(a,null,"processing",[a,b])}function pb(a){var b=h(a.nTable);b.attr("role",
|
||||
"grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),o=h(b[0].cloneNode(!1)),m=b.children("tfoot");c.sX&&"100%"===b.attr("width")&&b.removeAttr("width");m.length||(m=null);c=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:s(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",
|
||||
width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append(b.children("thead")))).append("top"===j?g:null)).append(h("<div/>",{"class":f.sScrollBody}).css({overflow:"auto",height:!e?null:s(e),width:!d?null:s(d)}).append(b));m&&c.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:s(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(o.removeAttr("id").css("margin-left",0).append(b.children("tfoot")))).append("bottom"===j?g:
|
||||
null));var b=c.children(),n=b[0],f=b[1],k=m?b[2]:null;d&&h(f).scroll(function(){var a=this.scrollLeft;n.scrollLeft=a;m&&(k.scrollLeft=a)});a.nScrollHead=n;a.nScrollBody=f;a.nScrollFoot=k;a.aoDrawCallback.push({fn:W,sName:"scrolling"});return c[0]}function W(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,f=b.iBarWidth,g=h(a.nScrollHead),j=g[0].style,i=g.children("div"),o=i[0].style,m=i.children("table"),i=a.nScrollBody,n=h(i),k=i.style,l=h(a.nScrollFoot).children("div"),p=l.children("table"),r=h(a.nTHead),
|
||||
q=h(a.nTable),da=q[0],M=da.style,J=a.nTFoot?h(a.nTFoot):null,u=a.oBrowser,v=u.bScrollOversize,y,t,x,w,z,A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};q.children("thead, tfoot").remove();z=r.clone().prependTo(q);y=r.find("tr");x=z.find("tr");z.find("th, td").removeAttr("tabindex");J&&(w=J.clone().prependTo(q),t=J.find("tr"),w=w.find("tr"));c||(k.width="100%",g[0].style.width="100%");h.each(ma(a,z),function(b,c){D=
|
||||
ga(a,b);c.style.width=a.aoColumns[D].sWidth});J&&F(function(a){a.style.width=""},w);b.bCollapse&&""!==e&&(k.height=n[0].offsetHeight+r[0].offsetHeight+"px");g=q.outerWidth();if(""===c){if(M.width="100%",v&&(q.find("tbody").height()>i.offsetHeight||"scroll"==n.css("overflow-y")))M.width=s(q.outerWidth()-f)}else""!==d?M.width=s(d):g==n.width()&&n.height()<q.height()?(M.width=s(g-f),q.outerWidth()>g-f&&(M.width=s(g))):M.width=s(g);g=q.outerWidth();F(E,x);F(function(a){C.push(a.innerHTML);A.push(s(h(a).css("width")))},
|
||||
x);F(function(a,b){a.style.width=A[b]},y);h(x).height(0);J&&(F(E,w),F(function(a){B.push(s(h(a).css("width")))},w),F(function(a,b){a.style.width=B[b]},t),h(w).height(0));F(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width=A[b]},x);J&&F(function(a,b){a.innerHTML="";a.style.width=B[b]},w);if(q.outerWidth()<g){t=i.scrollHeight>i.offsetHeight||"scroll"==n.css("overflow-y")?g+f:g;if(v&&(i.scrollHeight>i.offsetHeight||"scroll"==n.css("overflow-y")))M.width=
|
||||
s(t-f);(""===c||""!==d)&&P(a,1,"Possible column misalignment",6)}else t="100%";k.width=s(t);j.width=s(t);J&&(a.nScrollFoot.style.width=s(t));!e&&v&&(k.height=s(da.offsetHeight+f));e&&b.bCollapse&&(k.height=s(e),b=c&&da.offsetWidth>i.offsetWidth?f:0,da.offsetHeight<i.offsetHeight&&(k.height=s(da.offsetHeight+b)));b=q.outerWidth();m[0].style.width=s(b);o.width=s(b);m=q.height()>i.clientHeight||"scroll"==n.css("overflow-y");u="padding"+(u.bScrollbarLeft?"Left":"Right");o[u]=m?f+"px":"0px";J&&(p[0].style.width=
|
||||
s(b),l[0].style.width=s(b),l[0].style[u]=m?f+"px":"0px");n.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)i.scrollTop=0}function F(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Ca(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,j=c.length,d=X(a,"bVisible"),i=h("th",a.nTHead),o=b.getAttribute("width"),m=b.parentNode,n=!1,k,l;for(k=0;k<
|
||||
d.length;k++)l=c[d[k]],null!==l.sWidth&&(l.sWidth=Cb(l.sWidthOrig,m),n=!0);if(!n&&!f&&!e&&j==Z(a)&&j==i.length)for(k=0;k<j;k++)c[k].sWidth=s(i.eq(k).width());else{j=h(b).clone().empty().css("visibility","hidden").removeAttr("id").append(h(a.nTHead).clone(!1)).append(h(a.nTFoot).clone(!1)).append(h("<tbody><tr/></tbody>"));j.find("tfoot th, tfoot td").css("width","");var p=j.find("tbody tr"),i=ma(a,j.find("thead")[0]);for(k=0;k<d.length;k++)l=c[d[k]],i[k].style.width=null!==l.sWidthOrig&&""!==l.sWidthOrig?
|
||||
s(l.sWidthOrig):"";if(a.aoData.length)for(k=0;k<d.length;k++)n=d[k],l=c[n],h(Db(a,n)).clone(!1).append(l.sContentPadding).appendTo(p);j.appendTo(m);f&&g?j.width(g):f?(j.css("width","auto"),j.width()<m.offsetWidth&&j.width(m.offsetWidth)):e?j.width(m.offsetWidth):o&&j.width(o);Eb(a,j[0]);if(f){for(k=g=0;k<d.length;k++)l=c[d[k]],e=h(i[k]).outerWidth(),g+=null===l.sWidthOrig?e:parseInt(l.sWidth,10)+e-h(i[k]).width();j.width(s(g));b.style.width=s(g)}for(k=0;k<d.length;k++)if(l=c[d[k]],e=h(i[k]).width())l.sWidth=
|
||||
s(e);b.style.width=s(j.css("width"));j.remove()}o&&(b.style.width=s(o));if((o||f)&&!a._reszEvt)h(za).bind("resize.DT-"+a.sInstance,Ma(function(){V(a)})),a._reszEvt=!0}function Ma(a,b){var c=b||200,d,e;return function(){var b=this,g=+new Date,j=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=l;a.apply(b,j)},c)):d?(d=g,a.apply(b,j)):d=g}}function Cb(a,b){if(!a)return 0;var c=h("<div/>").css("width",s(a)).appendTo(b||O.body),d=c[0].offsetWidth;c.remove();return d}function Eb(a,b){var c=
|
||||
a.oScroll;if(c.sX||c.sY)c=!c.sX?c.iBarWidth:0,b.style.width=s(h(b).outerWidth()-c)}function Db(a,b){var c=Fb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(A(a,c,b,"display"))[0]:d.anCells[b]}function Fb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=A(a,f,b,"display")+"",c=c.replace(Xb,""),c.length>d&&(d=c.length,e=f);return e}function s(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function Gb(){if(!p.__scrollbarWidth){var a=
|
||||
h("<p/>").css({width:"100%",height:200,padding:0})[0],b=h("<div/>").css({position:"absolute",top:0,left:0,width:200,height:150,padding:0,overflow:"hidden",visibility:"hidden"}).append(a).appendTo("body"),c=a.offsetWidth;b.css("overflow","scroll");a=a.offsetWidth;c===a&&(a=b[0].clientWidth);b.remove();p.__scrollbarWidth=c-a}return p.__scrollbarWidth}function R(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var o=[];f=function(a){a.length&&!h.isArray(a[0])?o.push(a):o.push.apply(o,
|
||||
a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<o.length;a++){i=o[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||"string",d.push({src:i,col:g,dir:o[a][1],index:o[a][2],type:j,formatter:p.ext.type.order[j+"-pre"]})}return d}function kb(a){var b,c,d=[],e=p.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Da(a);h=R(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Hb(a,j.col);if("ssp"!=z(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=
|
||||
b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,l=f[a]._aSortData,p=f[b]._aSortData;for(g=0;g<i;g++)if(j=h[g],c=l[j.col],e=p[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,l=h.length,p=f[a]._aSortData,r=f[b]._aSortData;for(j=0;j<l;j++)if(i=h[j],c=p[i.col],g=r[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Ib(a){for(var b,c,
|
||||
d=a.aoColumns,e=R(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Sa(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a){var b=a._idx;b===l&&(b=h.inArray(a[1],
|
||||
f));return b+1>=f.length?0:b+1};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,C(e,"0")),-1!==c?(b=g(e[c]),e[c][1]=f[b],e[c]._idx=b):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);L(a);"function"==typeof d&&d(a)}function Ka(a,b,c,d){var e=a.aoColumns[c];Ta(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(B(a,!0),setTimeout(function(){Sa(a,c,b.shiftKey,
|
||||
d);"ssp"!==z(a)&&B(a,!1)},0)):Sa(a,c,b.shiftKey,d))})}function sa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=R(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(C(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(C(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Hb(a,b){var c=a.aoColumns[b],d=p.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,Y(a,b)));for(var f,g=p.ext.type.order[c.sType+
|
||||
"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:A(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function ta(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:yb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:yb(a.aoPreSearchCols[d])}})};u(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=
|
||||
b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Jb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&e.time&&(b=u(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&e.time<+new Date-1E3*b)&&d.length===e.columns.length))){a.oLoadedState=h.extend(!0,{},e);a._iDisplayStart=e.start;a.iInitDisplayStart=e.start;a._iDisplayLength=e.length;a.aaSorting=[];h.each(e.order,function(b,c){a.aaSorting.push(c[0]>=
|
||||
d.length?[0,c[1]]:c)});h.extend(a.oPreviousSearch,zb(e.search));b=0;for(c=e.columns.length;b<c;b++){var f=e.columns[b];d[b].bVisible=f.visible;h.extend(a.aoPreSearchCols[b],zb(f.search))}u(a,"aoStateLoaded","stateLoaded",[a,e])}}}function ua(a){var b=p.settings,a=h.inArray(a,C(b,"nTable"));return-1!==a?b[a]:null}function P(a,b,c,d){c="DataTables warning: "+(null!==a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)za.console&&
|
||||
console.log&&console.log(c);else if(a=p.ext,"alert"==(a.sErrMode||a.errMode))alert(c);else throw Error(c);}function D(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?D(a,b,d[0],d[1]):D(a,b,d)}):(d===l&&(d=c),b[c]!==l&&(a[d]=b[c]))}function Kb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Ta(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();
|
||||
c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function x(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function u(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&h(a.nTable).trigger(c+".dt",d);return e}function Qa(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;c===a.fnRecordsDisplay()&&(b=c-d);if(-1===d||0>b)b=0;a._iDisplayStart=b}function La(a,b){var c=
|
||||
a.renderer,d=p.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function z(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function Ua(a,b){var c=[],c=Lb.numbers_length,d=Math.floor(c/2);b<=c?c=S(0,b):a<=d?(c=S(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=S(b-(c-2),b):(c=S(a-1,a+2),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function cb(a){h.each({num:function(b){return va(b,
|
||||
a)},"num-fmt":function(b){return va(b,a,Va)},"html-num":function(b){return va(b,a,wa)},"html-num-fmt":function(b){return va(b,a,wa,Va)}},function(b,c){t.type.order[b+a+"-pre"]=c})}function Mb(a){return function(){var b=[ua(this[p.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return p.ext.internal[a].apply(this,b)}}var p,t,q,r,v,Wa={},Nb=/[\r\n]/g,wa=/<.*?>/g,Yb=/^[\w\+\-]/,Zb=/[\w\+\-]$/,Vb=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Va=/[',$\u00a3\u20ac\u00a5%\u2009\u202F]/g,
|
||||
H=function(a){return!a||!0===a||"-"===a?!0:!1},Ob=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Pb=function(a,b){Wa[b]||(Wa[b]=RegExp(Oa(b),"g"));return"string"===typeof a?a.replace(/\./g,"").replace(Wa[b],"."):a},Xa=function(a,b,c){var d="string"===typeof a;b&&d&&(a=Pb(a,b));c&&d&&(a=a.replace(Va,""));return H(a)||!isNaN(parseFloat(a))&&isFinite(a)},Qb=function(a,b,c){return H(a)?!0:!(H(a)||"string"===typeof a)?null:Xa(a.replace(wa,""),b,c)?!0:null},C=function(a,b,c){var d=
|
||||
[],e=0,f=a.length;if(c!==l)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},xa=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==l)for(;f<g;f++)e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},S=function(a,b){var c=[],d;b===l?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Ja=function(a){var b=[],c,d,e=a.length,f,g=0;d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b},w=function(a,
|
||||
b,c){a[b]!==l&&(a[c]=a[b])},$=/\[.*?\]$/,Q=/\(\)$/,qa=h("<div>")[0],Wb=qa.textContent!==l,Xb=/<.*?>/g;p=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new q(ua(this[t.iApiIndex])):new q(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===l||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=
|
||||
function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===l||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&W(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===l||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===l||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(!a)};
|
||||
this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===l?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==l){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==l||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==l?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();
|
||||
return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===l||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===l||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return ua(this[t.iApiIndex])};
|
||||
this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===l||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===l||e)&&h.columns.adjust();(d===l||d)&&h.draw();return 0};this.fnVersionCheck=t.fnVersionCheck;var b=this,c=a===l,d=this.length;c&&(a={});this.oApi=this.internal=t.internal;for(var e in p.ext.internal)e&&(this[e]=Mb(e));this.each(function(){var e={},g=1<d?Kb(e,a,!0):
|
||||
a,j=0,i,o=this.getAttribute("id"),e=!1,m=p.defaults;if("table"!=this.nodeName.toLowerCase())P(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{db(m);eb(m.column);G(m,m,!0);G(m.column,m.column,!0);G(m,g);var n=p.settings,j=0;for(i=n.length;j<i;j++){if(n[j].nTable==this){i=g.bRetrieve!==l?g.bRetrieve:m.bRetrieve;if(c||i)return n[j].oInstance;if(g.bDestroy!==l?g.bDestroy:m.bDestroy){n[j].oInstance.fnDestroy();break}else{P(n[j],0,"Cannot reinitialise DataTable",3);return}}if(n[j].sTableId==
|
||||
this.id){n.splice(j,1);break}}if(null===o||""===o)this.id=o="DataTables_Table_"+p.ext._unique++;var k=h.extend(!0,{},p.models.oSettings,{nTable:this,oApi:b.internal,oInit:g,sDestroyWidth:h(this)[0].style.width,sInstance:o,sTableId:o});n.push(k);k.oInstance=1===b.length?b:h(this).dataTable();db(g);g.oLanguage&&N(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=h.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=Kb(h.extend(!0,{},m),g);D(k.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));
|
||||
D(k,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);D(k.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],
|
||||
["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);D(k.oLanguage,g,"fnInfoCallback");x(k,"aoDrawCallback",g.fnDrawCallback,"user");x(k,"aoServerParams",g.fnServerParams,"user");x(k,"aoStateSaveParams",g.fnStateSaveParams,"user");x(k,"aoStateLoadParams",g.fnStateLoadParams,"user");x(k,"aoStateLoaded",g.fnStateLoaded,"user");x(k,"aoRowCallback",g.fnRowCallback,"user");x(k,"aoRowCreatedCallback",g.fnCreatedRow,"user");x(k,"aoHeaderCallback",g.fnHeaderCallback,"user");x(k,"aoFooterCallback",g.fnFooterCallback,
|
||||
"user");x(k,"aoInitComplete",g.fnInitComplete,"user");x(k,"aoPreDrawCallback",g.fnPreDrawCallback,"user");o=k.oClasses;g.bJQueryUI?(h.extend(o,p.ext.oJUIClasses,g.oClasses),g.sDom===m.sDom&&"lfrtip"===m.sDom&&(k.sDom='<"H"lfr>t<"F"ip>'),k.renderer)?h.isPlainObject(k.renderer)&&!k.renderer.header&&(k.renderer.header="jqueryui"):k.renderer="jqueryui":h.extend(o,p.ext.classes,g.oClasses);h(this).addClass(o.sTable);if(""!==k.oScroll.sX||""!==k.oScroll.sY)k.oScroll.iBarWidth=Gb();!0===k.oScroll.sX&&(k.oScroll.sX=
|
||||
"100%");k.iInitDisplayStart===l&&(k.iInitDisplayStart=g.iDisplayStart,k._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(k.bDeferLoading=!0,j=h.isArray(g.iDeferLoading),k._iRecordsDisplay=j?g.iDeferLoading[0]:g.iDeferLoading,k._iRecordsTotal=j?g.iDeferLoading[1]:g.iDeferLoading);""!==g.oLanguage.sUrl?(k.oLanguage.sUrl=g.oLanguage.sUrl,h.getJSON(k.oLanguage.sUrl,null,function(a){N(a);G(m.oLanguage,a);h.extend(true,k.oLanguage,g.oLanguage,a);ra(k)}),e=!0):h.extend(!0,k.oLanguage,g.oLanguage);
|
||||
null===g.asStripeClasses&&(k.asStripeClasses=[o.sStripeOdd,o.sStripeEven]);var j=k.asStripeClasses,r=h("tbody tr:eq(0)",this);-1!==h.inArray(!0,h.map(j,function(a){return r.hasClass(a)}))&&(h("tbody tr",this).removeClass(j.join(" ")),k.asDestroyStripes=j.slice());var n=[],q,j=this.getElementsByTagName("thead");0!==j.length&&(aa(k.aoHeader,j[0]),n=ma(k));if(null===g.aoColumns){q=[];j=0;for(i=n.length;j<i;j++)q.push(null)}else q=g.aoColumns;j=0;for(i=q.length;j<i;j++)Aa(k,n?n[j]:null);hb(k,g.aoColumnDefs,
|
||||
q,function(a,b){fa(k,a,b)});if(r.length){var s=function(a,b){return a.getAttribute("data-"+b)?b:null};h.each(ia(k,r[0]).cells,function(a,b){var c=k.aoColumns[a];if(c.mData===a){var d=s(b,"sort")||s(b,"order"),e=s(b,"filter")||s(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:l,type:d!==null?a+".@data-"+d:l,filter:e!==null?a+".@data-"+e:l};fa(k,a)}}})}var t=k.oFeatures;g.bStateSave&&(t.bStateSave=!0,Jb(k,g),x(k,"aoDrawCallback",ta,"state_save"));if(g.aaSorting===
|
||||
l){n=k.aaSorting;j=0;for(i=n.length;j<i;j++)n[j][1]=k.aoColumns[j].asSorting[0]}sa(k);t.bSort&&x(k,"aoDrawCallback",function(){if(k.bSorted){var a=R(k),b={};h.each(a,function(a,c){b[c.src]=c.dir});u(k,null,"order",[k,a,b]);Ib(k)}});x(k,"aoDrawCallback",function(){(k.bSorted||z(k)==="ssp"||t.bDeferRender)&&sa(k)},"sc");fb(k);j=h(this).children("caption").each(function(){this._captionSide=h(this).css("caption-side")});i=h(this).children("thead");0===i.length&&(i=h("<thead/>").appendTo(this));k.nTHead=
|
||||
i[0];i=h(this).children("tbody");0===i.length&&(i=h("<tbody/>").appendTo(this));k.nTBody=i[0];i=h(this).children("tfoot");if(0===i.length&&0<j.length&&(""!==k.oScroll.sX||""!==k.oScroll.sY))i=h("<tfoot/>").appendTo(this);0===i.length||0===i.children().length?h(this).addClass(o.sNoFooter):0<i.length&&(k.nTFoot=i[0],aa(k.aoFooter,k.nTFoot));if(g.aaData)for(j=0;j<g.aaData.length;j++)I(k,g.aaData[j]);else(k.bDeferLoading||"dom"==z(k))&&ha(k,h(k.nTBody).children("tr"));k.aiDisplay=k.aiDisplayMaster.slice();
|
||||
k.bInitialised=!0;!1===e&&ra(k)}});b=null;return this};var Rb=[],y=Array.prototype,$b=function(a){var b,c,d=p.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};
|
||||
q=function(a,b){if(!this instanceof q)throw"DT API must be constructed as a new object";var c=[],d=function(a){(a=$b(a))&&c.push.apply(c,a)};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=Ja(c);b&&this.push.apply(this,b.toArray?b.toArray():b);this.selector={rows:null,cols:null,opts:null};q.extend(this,this,Rb)};p.Api=q;q.prototype={concat:y.concat,context:[],each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=
|
||||
this.context;return b.length>a?new q(b[a],this[a]):null},filter:function(a){var b=[];if(y.filter)b=y.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new q(this.context,b)},flatten:function(){var a=[];return new q(this.context,a.concat.apply(a,this.toArray()))},join:y.join,indexOf:y.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c){var d=[],e,f,g,h,i,o=this.context,
|
||||
m,n,k=this.selector;"string"===typeof a&&(c=b,b=a,a=!1);f=0;for(g=o.length;f<g;f++)if("table"===b)e=c(o[f],f),e!==l&&d.push(e);else if("columns"===b||"rows"===b)e=c(o[f],this[f],f),e!==l&&d.push(e);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){n=this[f];"column-rows"===b&&(m=Ya(o[f],k.opts));h=0;for(i=n.length;h<i;h++)e=n[h],e="cell"===b?c(o[f],e.row,e.column,f,h):c(o[f],e,f,h,m),e!==l&&d.push(e)}return d.length?(a=new q(o,a?d.concat.apply([],d):d),b=a.selector,b.rows=k.rows,b.cols=
|
||||
k.cols,b.opts=k.opts,a):this},lastIndexOf:y.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(y.map)b=y.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new q(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:y.pop,push:y.push,reduce:y.reduce||function(a,b){return gb(this,a,b,0,this.length,1)},reduceRight:y.reduceRight||function(a,b){return gb(this,
|
||||
a,b,this.length-1,-1,-1)},reverse:y.reverse,selector:null,shift:y.shift,sort:y.sort,splice:y.splice,toArray:function(){return y.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},unique:function(){return new q(this.context,Ja(this))},unshift:y.unshift};q.extend=function(a,b,c){if(b&&(b instanceof q||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);q.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]=
|
||||
"function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,q.extend(a,b[f.name],f.propExt)}};q.register=r=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<d;c++)q.register(a[c],b);else for(var e=a.split("."),f=Rb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var o=f.length;i<o;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:
|
||||
i.propExt}};q.registerPlural=v=function(a,b,c){q.register(a,c);q.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof q?a.length?h.isArray(a[0])?new q(a.context,a[0]):a[0]:l:a})};r("tables()",function(a){var b;if(a){b=q;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});r("table()",function(a){var a=this.tables(a),
|
||||
b=a.context;return b.length?new q(b[0]):a});v("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable})});v("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody})});v("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead})});v("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot})});v("tables().containers()",
|
||||
"table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper})});r("draw()",function(a){return this.iterator("table",function(b){L(b,!1===a)})});r("page()",function(a){return a===l?this.page.info().page:this.iterator("table",function(b){Ra(b,a)})});r("page.info()",function(){if(0===this.context.length)return l;var a=this.context[0],b=a._iDisplayStart,c=a._iDisplayLength,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,
|
||||
end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d}});r("page.len()",function(a){return a===l?0!==this.context.length?this.context[0]._iDisplayLength:l:this.iterator("table",function(b){Pa(b,a)})});var Sb=function(a,b,c){"ssp"==z(a)?L(a,b):(B(a,!0),na(a,[],function(c){ja(a);for(var c=oa(a,c),d=0,g=c.length;d<g;d++)I(a,c[d]);L(a,b);B(a,!1)}));if(c){var d=new q(a);d.one("draw",function(){c(d.ajax.json())})}};r("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});
|
||||
r("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});r("ajax.reload()",function(a,b){return this.iterator("table",function(c){Sb(c,!1===b,a)})});r("ajax.url()",function(a){var b=this.context;if(a===l){if(0===b.length)return l;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});r("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Sb(c,
|
||||
!1===b,a)})});var Za=function(a,b){var c=[],d,e,f,g,j,i;if(!a||"string"===typeof a||a.length===l)a=[a];f=0;for(g=a.length;f<g;f++){e=a[f]&&a[f].split?a[f].split(","):[a[f]];j=0;for(i=e.length;j<i;j++)(d=b("string"===typeof e[j]?h.trim(e[j]):e[j]))&&d.length&&c.push.apply(c,d)}return c},$a=function(a){a||(a={});a.filter&&!a.search&&(a.search=a.filter);return{search:a.search||"none",order:a.order||"current",page:a.page||"all"}},ab=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=
|
||||
a[b],a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ya=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==z(a))return"removed"===j?[]:S(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==
|
||||
j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};r("rows()",function(a,b){a===l?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(c){var e=b;return Za(a,function(a){var b=Ob(a);if(b!==null&&!e)return[b];var j=Ya(c,e);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;for(var b=[],i=0,o=j.length;i<o;i++)b.push(c.aoData[j[i]].nTr);return a.nodeName&&h.inArray(a,b)!==-1?[a._DT_RowIndex]:h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()})});
|
||||
c.selector.rows=a;c.selector.opts=b;return c});r("rows().nodes()",function(){return this.iterator("row",function(a,b){return a.aoData[b].nTr||l})});r("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return xa(a.aoData,b,"_aData")})});v("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData})});v("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,
|
||||
c){la(b,c,a)})});v("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,b){return b})});v("rows().remove()","row().remove()",function(){var a=this;return this.iterator("row",function(b,c,d){var e=b.aoData;e.splice(c,1);for(var f=0,g=e.length;f<g;f++)null!==e[f].nTr&&(e[f].nTr._DT_RowIndex=f);h.inArray(c,b.aiDisplay);ka(b.aiDisplayMaster,c);ka(b.aiDisplay,c);ka(a[d],c,!1);Qa(b)})});r("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;
|
||||
for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ha(b,c)[0]):h.push(I(b,c));return h}),c=this.rows(-1);c.pop();c.push.apply(c,b.toArray());return c});r("row()",function(a,b){return ab(this.rows(a,b))});r("row().data()",function(a){var b=this.context;if(a===l)return b.length&&this.length?b[0].aoData[this[0]]._aData:l;b[0].aoData[this[0]]._aData=a;la(b[0],this[0],"data");return this});r("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||
|
||||
null:null});r("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?ha(b,a)[0]:I(b,a)});return this.row(b[0])});var bb=function(a){var b=a.context;b.length&&a.length&&(a=b[0].aoData[a[0]],a._details&&(a._details.remove(),a._detailsShow=l,a._details=l))},Tb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();
|
||||
var e=c[0],f=new q(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<C(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=Z(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,
|
||||
b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&bb(g[c])}))}}};r("row().child()",function(a,b){var c=this.context;if(a===l)return c.length&&this.length?c[0].aoData[this[0]]._details:l;if(!0===a)this.child.show();else if(!1===a)bb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(a.nodeName&&"tr"===a.nodeName.toLowerCase())e.push(a);else{var c=h("<tr><td/></tr>").addClass(b);h("td",c).addClass(b).html(a)[0].colSpan=Z(d);e.push(c[0])}};if(h.isArray(a)||
|
||||
a instanceof h)for(var g=0,j=a.length;g<j;g++)f(a[g],b);else f(a,b);c._details&&c._details.remove();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});r(["row().child.show()","row().child().show()"],function(){Tb(this,!0);return this});r(["row().child.hide()","row().child().hide()"],function(){Tb(this,!1);return this});r(["row().child.remove()","row().child().remove()"],function(){bb(this);return this});r("row().child.isShown()",function(){var a=this.context;return a.length&&
|
||||
this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var ac=/^(.*):(name|visIdx|visible)$/;r("columns()",function(a,b){a===l?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(b){var c=a,f=b.aoColumns,g=C(f,"sName"),j=C(f,"nTh");return Za(c,function(a){var c=Ob(a);if(a==="")return S(f.length);if(c!==null)return[c>=0?c:f.length+c];var e=typeof a==="string"?a.match(ac):"";if(e)switch(e[2]){case "visIdx":case "visible":a=parseInt(e[1],10);if(a<0){c=h.map(f,function(a,
|
||||
b){return a.bVisible?b:null});return[c[c.length+a]]}return[ga(b,a)];case "name":return h.map(g,function(a,b){return a===e[1]?b:null})}else return h(j).filter(a).map(function(){return h.inArray(this,j)}).toArray()})});c.selector.cols=a;c.selector.opts=b;return c});v("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh})});v("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf})});
|
||||
v("columns().data()","column().data()",function(){return this.iterator("column-rows",function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(A(a,e[d],b,""));return c})});v("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return xa(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)})});v("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return xa(a.aoData,e,"anCells",b)})});v("columns().visible()",
|
||||
"column().visible()",function(a){return this.iterator("column",function(b,c){var d;if(a===l)d=b.aoColumns[c].bVisible;else{var e=b.aoColumns;d=e[c];var f=b.aoData,g,j,i;if(a===l)d=d.bVisible;else{if(d.bVisible!==a){if(a){var o=h.inArray(!0,C(e,"bVisible"),c+1);g=0;for(j=f.length;g<j;g++)i=f[g].nTr,e=f[g].anCells,i&&i.insertBefore(e[c],e[o]||null)}else h(C(b.aoData,"anCells",c)).detach();d.bVisible=a;ba(b,b.aoHeader);ba(b,b.aoFooter);V(b);(b.oScroll.sX||b.oScroll.sY)&&W(b);u(b,null,"column-visibility",
|
||||
[b,c,a]);ta(b)}d=void 0}}return d})});v("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?Y(b,c):c})});r("columns.adjust()",function(){return this.iterator("table",function(a){V(a)})});r("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return ga(c,b);if("fromData"===a||"toVisible"===a)return Y(c,b)}});r("column()",function(a,b){return ab(this.columns(a,b))});r("cells()",
|
||||
function(a,b,c){h.isPlainObject(a)&&(typeof a.row!==l?(c=b,b=null):(c=a,a=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===l)return this.iterator("table",function(b){var d=a,e=$a(c),f=b.aoData,g=Ya(b,e),e=xa(f,g,"anCells"),i=h([].concat.apply([],e)),j,m=b.aoColumns.length,o,p,r,q;return Za(d,function(a){if(a===null||a===l){o=[];p=0;for(r=g.length;p<r;p++){j=g[p];for(q=0;q<m;q++)o.push({row:j,column:q})}return o}return h.isPlainObject(a)?[a]:i.filter(a).map(function(a,b){j=b.parentNode._DT_RowIndex;
|
||||
return{row:j,column:h.inArray(b,f[j].anCells)}}).toArray()})});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,o,m=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(o=d[b].length;i<o;i++)f.push({row:e[b][g],column:d[b][i]})}return f});h.extend(m.selector,{cols:b,rows:a,opts:c});return m});v("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return a.aoData[b].anCells[c]})});r("cells().data()",function(){return this.iterator("cell",
|
||||
function(a,b,c){return A(a,b,c)})});v("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]})});v("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:Y(a,c)}})});r(["cells().invalidate()","cell().invalidate()"],function(a){var b=this.selector;this.rows(b.rows,b.opts).invalidate(a);return this});r("cell()",function(a,b,
|
||||
c){return ab(this.cells(a,b,c))});r("cell().data()",function(a){var b=this.context,c=this[0];if(a===l)return b.length&&c.length?A(b[0],c[0].row,c[0].column):l;Ea(b[0],c[0].row,c[0].column,a);la(b[0],c[0].row,"data",c[0].column);return this});r("order()",function(a,b){var c=this.context;if(a===l)return 0!==c.length?c[0].aaSorting:l;"number"===typeof a?a=[[a,b]]:h.isArray(a[0])||(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});r("order.listener()",
|
||||
function(a,b,c){return this.iterator("table",function(d){Ka(d,a,b,c)})});r(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});r("search()",function(a,b,c,d){var e=this.context;return a===l?0!==e.length?e[0].oPreviousSearch.sSearch:l:this.iterator("table",function(e){e.oFeatures.bFilter&&ca(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:
|
||||
c,bCaseInsensitive:null===d?!0:d}),1)})});r(["columns().search()","column().search()"],function(a,b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===l)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ca(e,e.oPreviousSearch,1))})});r("state()",function(){return this.context.length?this.context[0].oSavedState:null});r("state.clear()",function(){return this.iterator("table",
|
||||
function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});r("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});r("state.save()",function(){return this.iterator("table",function(a){ta(a)})});p.versionCheck=p.fnVersionCheck=function(a){for(var b=p.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};p.isDataTable=p.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(p.settings,
|
||||
function(a,e){if(e.nTable===b||e.nScrollHead===b||e.nScrollFoot===b)c=!0});return c};p.tables=p.fnTables=function(a){return jQuery.map(p.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable})};p.camelToHungarian=G;r("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){r(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||(a[0]+=".dt");var d=
|
||||
h(this.tables().nodes());d[b].apply(d,a);return this})});r("clear()",function(){return this.iterator("table",function(a){ja(a)})});r("settings()",function(){return new q(this.context,this.context)});r("data()",function(){return this.iterator("table",function(a){return C(a.aoData,"_aData")}).flatten()});r("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),l=h(b.nTableWrapper),
|
||||
m=h.map(b.aoData,function(a){return a.nTr}),n;b.bDestroying=!0;u(b,"aoDestroyCallback","destroy",[b]);a||(new q(b)).columns().visible(!0);l.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(za).unbind(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));i.detach();l.detach();b.aaSorting=[];b.aaSortingFixed=[];sa(b);h(m).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+
|
||||
" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));!a&&c&&c.insertBefore(e,b.nTableReinsertBefore);f.children().detach();f.append(m);i.css("width",b.sDestroyWidth).removeClass(d.sTable);(n=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%n])});c=h.inArray(b,p.settings);-1!==c&&p.settings.splice(c,
|
||||
1)})});p.version="1.10.1";p.settings=[];p.models={};p.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};p.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null};p.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,
|
||||
sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};p.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,
|
||||
bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},
|
||||
fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",
|
||||
sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},p.models.oSearch),sAjaxDataProp:"data",
|
||||
sAjaxSource:null,sDom:"lfrtip",sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null};T(p.defaults);p.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};T(p.defaults.column);p.models.oSettings={oFeatures:{bAutoWidth:null,
|
||||
bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,
|
||||
asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,
|
||||
bAjaxDataGet:!0,jqXHR:null,json:l,oAjaxData:l,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==z(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==z(this)?1*this._iRecordsDisplay:
|
||||
this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{}};p.ext=t={classes:{},errMode:"alert",feature:[],search:[],internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],
|
||||
search:{},order:{}},_unique:0,fnVersionCheck:p.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:p.version};h.extend(t,{afnFiltering:t.search,aTypes:t.type.detect,ofnSearch:t.type.search,oSort:t.type.order,afnSortData:t.order,aoFeatures:t.feature,oApi:t.internal,oStdClasses:t.classes,oPagination:t.pager});h.extend(p.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",
|
||||
sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",
|
||||
sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var ya="",ya="",E=ya+"ui-state-default",ea=ya+"css_right ui-icon ui-icon-",Ub=ya+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(p.ext.oJUIClasses,p.ext.classes,{sPageButton:"fg-button ui-button "+
|
||||
E,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:E+" sorting_asc",sSortDesc:E+" sorting_desc",sSortable:E+" sorting",sSortableAsc:E+" sorting_asc_disabled",sSortableDesc:E+" sorting_desc_disabled",sSortableNone:E+" sorting_disabled",sSortJUIAsc:ea+"triangle-1-n",sSortJUIDesc:ea+"triangle-1-s",sSortJUI:ea+"carat-2-n-s",sSortJUIAscAllowed:ea+"carat-1-n",sSortJUIDescAllowed:ea+
|
||||
"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+E,sScrollFoot:"dataTables_scrollFoot "+E,sHeaderTH:E,sFooterTH:E,sJUIHeader:Ub+" ui-corner-tl ui-corner-tr",sJUIFooter:Ub+" ui-corner-bl ui-corner-br"});var Lb=p.ext.pager;h.extend(Lb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},simple_numbers:function(a,b){return["previous",Ua(a,b),"next"]},full_numbers:function(a,b){return["first",
|
||||
"previous",Ua(a,b),"next","last"]},_numbers:Ua,numbers_length:7});h.extend(!0,p.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i,l,m=0,n=function(b,d){var k,p,r,q,s=function(b){Ra(a,b.data.action,true)};k=0;for(p=d.length;k<p;k++){q=d[k];if(h.isArray(q)){r=h("<"+(q.DT_el||"div")+"/>").appendTo(b);n(r,q)}else{l=i="";switch(q){case "ellipsis":b.append("<span>…</span>");break;case "first":i=j.sFirst;l=q+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":i=
|
||||
j.sPrevious;l=q+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":i=j.sNext;l=q+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":i=j.sLast;l=q+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:i=q+1;l=e===q?g.sPageButtonActive:""}if(i){r=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof q==="string"?a.sTableId+"_"+q:null}).html(i).appendTo(b);Ta(r,{action:q},s);m++}}}};try{var k=h(O.activeElement).data("dt-idx");n(h(b).empty(),
|
||||
d);k!==null&&h(b).find("[data-dt-idx="+k+"]").focus()}catch(p){}}}});var va=function(a,b,c,d){if(!a||"-"===a)return-Infinity;b&&(a=Pb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(t.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return H(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return H(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,
|
||||
b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});cb("");h.extend(p.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Xa(a,c)?"num"+c:null},function(a){if(a&&(!Yb.test(a)||!Zb.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||H(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return Xa(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Qb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Qb(a,
|
||||
c,!0)?"html-num-fmt"+c:null},function(a){return H(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(p.ext.type.search,{html:function(a){return H(a)?a:"string"===typeof a?a.replace(Nb," ").replace(wa,""):""},string:function(a){return H(a)?a:"string"===typeof a?a.replace(Nb," "):a}});h.extend(!0,p.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?
|
||||
d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){var e=c.idx;h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(f,g,h,i){if(a===g){b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(i[e]=="asc"?d.sSortAsc:i[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+
|
||||
" "+d.sSortJUIDescAllowed).addClass(i[e]=="asc"?d.sSortJUIAsc:i[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});p.render={number:function(a,b,c,d){return{display:function(e){var f=0>e?"-":"",e=Math.abs(parseFloat(e)),g=parseInt(e,10),e=c?b+(e-g).toFixed(c).substring(2):"";return f+(d||"")+g.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+e}}}};h.extend(p.ext.internal,{_fnExternApiFunc:Mb,_fnBuildAjax:na,_fnAjaxUpdate:jb,_fnAjaxParameters:sb,_fnAjaxUpdateDraw:tb,_fnAjaxDataSrc:oa,_fnAddColumn:Aa,
|
||||
_fnColumnOptions:fa,_fnAdjustColumnSizing:V,_fnVisibleToColumnIndex:ga,_fnColumnIndexToVisible:Y,_fnVisbleColumns:Z,_fnGetColumns:X,_fnColumnTypes:Da,_fnApplyColumnDefs:hb,_fnHungarianMap:T,_fnCamelToHungarian:G,_fnLanguageCompat:N,_fnBrowserDetect:fb,_fnAddData:I,_fnAddTr:ha,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==l?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:A,_fnSetCellData:Ea,_fnSplitObjNotation:Ga,_fnGetObjectDataFn:U,
|
||||
_fnSetObjectDataFn:Ba,_fnGetDataMaster:Ha,_fnClearTable:ja,_fnDeleteIndex:ka,_fnInvalidateRow:la,_fnGetRowElements:ia,_fnCreateTr:Fa,_fnBuildHead:ib,_fnDrawHead:ba,_fnDraw:K,_fnReDraw:L,_fnAddOptionsHtml:lb,_fnDetectHeader:aa,_fnGetUniqueThs:ma,_fnFeatureHtmlFilter:nb,_fnFilterComplete:ca,_fnFilterCustom:wb,_fnFilterColumn:vb,_fnFilter:ub,_fnFilterCreateSearch:Na,_fnEscapeRegex:Oa,_fnFilterData:xb,_fnFeatureHtmlInfo:qb,_fnUpdateInfo:Ab,_fnInfoMacros:Bb,_fnInitialise:ra,_fnInitComplete:pa,_fnLengthChange:Pa,
|
||||
_fnFeatureHtmlLength:mb,_fnFeatureHtmlPaginate:rb,_fnPageChange:Ra,_fnFeatureHtmlProcessing:ob,_fnProcessingDisplay:B,_fnFeatureHtmlTable:pb,_fnScrollDraw:W,_fnApplyToChildren:F,_fnCalculateColumnWidths:Ca,_fnThrottle:Ma,_fnConvertToWidth:Cb,_fnScrollingWidthAdjust:Eb,_fnGetWidestNode:Db,_fnGetMaxLenString:Fb,_fnStringToCss:s,_fnScrollBarWidth:Gb,_fnSortFlatten:R,_fnSort:kb,_fnSortAria:Ib,_fnSortListener:Sa,_fnSortAttachListener:Ka,_fnSortingClasses:sa,_fnSortData:Hb,_fnSaveState:ta,_fnLoadState:Jb,
|
||||
_fnSettingsFromNode:ua,_fnLog:P,_fnMap:D,_fnBindAction:Ta,_fnCallbackReg:x,_fnCallbackFire:u,_fnLengthOverflow:Qa,_fnRenderer:La,_fnDataSource:z,_fnRowAttributes:Ia,_fnCalculateEnd:function(){}});h.fn.dataTable=p;h.fn.dataTableSettings=p.settings;h.fn.dataTableExt=p.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(p,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable};"function"===typeof define&&define.amd?define("datatables",["jquery"],N):"object"===typeof exports?N(require("jquery")):
|
||||
jQuery&&!jQuery.fn.dataTable&&N(jQuery)})(window,document);
|
23
clients/flash/web-client/src/main/resources/lib/jquery.json-2.4.min.js
vendored
Executable file
23
clients/flash/web-client/src/main/resources/lib/jquery.json-2.4.min.js
vendored
Executable file
@ -0,0 +1,23 @@
|
||||
/*! jQuery JSON plugin 2.4.0 | code.google.com/p/jquery-json */
|
||||
(function($){'use strict';var escape=/["\\\x00-\x1f\x7f-\x9f]/g,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},hasOwn=Object.prototype.hasOwnProperty;$.toJSON=typeof JSON==='object'&&JSON.stringify?JSON.stringify:function(o){if(o===null){return'null';}
|
||||
var pairs,k,name,val,type=$.type(o);if(type==='undefined'){return undefined;}
|
||||
if(type==='number'||type==='boolean'){return String(o);}
|
||||
if(type==='string'){return $.quoteString(o);}
|
||||
if(typeof o.toJSON==='function'){return $.toJSON(o.toJSON());}
|
||||
if(type==='date'){var month=o.getUTCMonth()+1,day=o.getUTCDate(),year=o.getUTCFullYear(),hours=o.getUTCHours(),minutes=o.getUTCMinutes(),seconds=o.getUTCSeconds(),milli=o.getUTCMilliseconds();if(month<10){month='0'+month;}
|
||||
if(day<10){day='0'+day;}
|
||||
if(hours<10){hours='0'+hours;}
|
||||
if(minutes<10){minutes='0'+minutes;}
|
||||
if(seconds<10){seconds='0'+seconds;}
|
||||
if(milli<100){milli='0'+milli;}
|
||||
if(milli<10){milli='0'+milli;}
|
||||
return'"'+year+'-'+month+'-'+day+'T'+
|
||||
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
|
||||
pairs=[];if($.isArray(o)){for(k=0;k<o.length;k++){pairs.push($.toJSON(o[k])||'null');}
|
||||
return'['+pairs.join(',')+']';}
|
||||
if(typeof o==='object'){for(k in o){if(hasOwn.call(o,k)){type=typeof k;if(type==='number'){name='"'+k+'"';}else if(type==='string'){name=$.quoteString(k);}else{continue;}
|
||||
type=typeof o[k];if(type!=='function'&&type!=='undefined'){val=$.toJSON(o[k]);pairs.push(name+':'+val);}}}
|
||||
return'{'+pairs.join(',')+'}';}};$.evalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(str){return eval('('+str+')');};$.secureEvalJSON=typeof JSON==='object'&&JSON.parse?JSON.parse:function(str){var filtered=str.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered)){return eval('('+str+')');}
|
||||
throw new SyntaxError('Error parsing JSON, source is not valid.');};$.quoteString=function(str){if(str.match(escape)){return'"'+str.replace(escape,function(a){var c=meta[a];if(typeof c==='string'){return c;}
|
||||
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
|
||||
return'"'+str+'"';};}(jQuery));
|
716
clients/flash/web-client/src/main/resources/lib/jquery.jsonrpcclient.js
Executable file
716
clients/flash/web-client/src/main/resources/lib/jquery.jsonrpcclient.js
Executable file
@ -0,0 +1,716 @@
|
||||
/*
|
||||
* Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
|
||||
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is jquery.jsonrpclient.js modified for Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Textalk AB http://textalk.se/
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* jquery.jsonrpclient.js - JSON RPC client code
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* This plugin requires jquery.json.js to be available, or at least the methods $.toJSON and
|
||||
* $.parseJSON.
|
||||
*
|
||||
* The plan is to make use of websockets if they are available, but work just as well with only
|
||||
* http if not.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* var foo = new $.JsonRpcClient({ ajaxUrl: '/backend/jsonrpc' });
|
||||
* foo.call(
|
||||
* 'bar', [ 'A parameter', 'B parameter' ],
|
||||
* function(result) { alert('Foo bar answered: ' + result.my_answer); },
|
||||
* function(error) { console.log('There was an error', error); }
|
||||
* );
|
||||
*
|
||||
* More examples are available in README.md
|
||||
*/
|
||||
(function($) {
|
||||
/**
|
||||
* @fn new
|
||||
* @memberof $.JsonRpcClient
|
||||
*
|
||||
* @param options An object stating the backends:
|
||||
* ajaxUrl A url (relative or absolute) to a http(s) backend.
|
||||
* socketUrl A url (relative of absolute) to a ws(s) backend.
|
||||
* onmessage A socket message handler for other messages (non-responses).
|
||||
* getSocket A function returning a WebSocket or null.
|
||||
* It must take an onmessage_cb and bind it to the onmessage event
|
||||
* (or chain it before/after some other onmessage handler).
|
||||
* Or, it could return null if no socket is available.
|
||||
* The returned instance must have readyState <= 1, and if less than 1,
|
||||
* react to onopen binding.
|
||||
*/
|
||||
$.JsonRpcClient = function(options) {
|
||||
var self = this;
|
||||
this.options = $.extend({
|
||||
ajaxUrl : null,
|
||||
socketUrl : null, ///< The ws-url for default getSocket.
|
||||
onmessage : null, ///< Other onmessage-handler.
|
||||
login : null, /// auth login
|
||||
passwd : null, /// auth passwd
|
||||
sessid : null,
|
||||
loginParams : null,
|
||||
userVariables : null,
|
||||
getSocket : function(onmessage_cb) { return self._getSocket(onmessage_cb); }
|
||||
}, options);
|
||||
|
||||
self.ws_cnt = 0;
|
||||
|
||||
// Declare an instance version of the onmessage callback to wrap 'this'.
|
||||
this.wsOnMessage = function(event) { self._wsOnMessage(event); };
|
||||
};
|
||||
|
||||
/// Holding the WebSocket on default getsocket.
|
||||
$.JsonRpcClient.prototype._ws_socket = null;
|
||||
|
||||
/// Object <id>: { success_cb: cb, error_cb: cb }
|
||||
$.JsonRpcClient.prototype._ws_callbacks = {};
|
||||
|
||||
/// The next JSON-RPC request id.
|
||||
$.JsonRpcClient.prototype._current_id = 1;
|
||||
|
||||
|
||||
$.JsonRpcClient.prototype.speedTest = function (bytes, cb) {
|
||||
var socket = this.options.getSocket(this.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
this.speedCB = cb;
|
||||
this.speedBytes = bytes;
|
||||
socket.send("#SPU " + bytes);
|
||||
|
||||
var loops = bytes / 1024;
|
||||
var rem = bytes % 1024;
|
||||
var i;
|
||||
var data = new Array(1024).join(".");
|
||||
for (i = 0; i < loops; i++) {
|
||||
socket.send("#SPB " + data);
|
||||
}
|
||||
|
||||
if (rem) {
|
||||
socket.send("#SPB " + data);
|
||||
}
|
||||
|
||||
socket.send("#SPE");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @fn call
|
||||
* @memberof $.JsonRpcClient
|
||||
*
|
||||
* @param method The method to run on JSON-RPC server.
|
||||
* @param params The params; an array or object.
|
||||
* @param success_cb A callback for successful request.
|
||||
* @param error_cb A callback for error.
|
||||
*/
|
||||
$.JsonRpcClient.prototype.call = function(method, params, success_cb, error_cb) {
|
||||
// Construct the JSON-RPC 2.0 request.
|
||||
|
||||
if (!params) {
|
||||
params = {};
|
||||
}
|
||||
|
||||
if (this.options.sessid) {
|
||||
params.sessid = this.options.sessid;
|
||||
}
|
||||
|
||||
var request = {
|
||||
jsonrpc : '2.0',
|
||||
method : method,
|
||||
params : params,
|
||||
id : this._current_id++ // Increase the id counter to match request/response
|
||||
};
|
||||
|
||||
if (!success_cb) {
|
||||
success_cb = function(e){console.log("Success: ", e);};
|
||||
}
|
||||
|
||||
if (!error_cb) {
|
||||
error_cb = function(e){console.log("Error: ", e);};
|
||||
}
|
||||
|
||||
// Try making a WebSocket call.
|
||||
var socket = this.options.getSocket(this.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
this._wsCall(socket, request, success_cb, error_cb);
|
||||
return;
|
||||
}
|
||||
|
||||
// No WebSocket, and no HTTP backend? This won't work.
|
||||
if (this.options.ajaxUrl === null) {
|
||||
throw "$.JsonRpcClient.call used with no websocket and no http endpoint.";
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : this.options.ajaxUrl,
|
||||
data : $.toJSON(request),
|
||||
dataType : 'json',
|
||||
cache : false,
|
||||
|
||||
success : function(data) {
|
||||
if ('error' in data) error_cb(data.error, this);
|
||||
success_cb(data.result, this);
|
||||
},
|
||||
|
||||
// JSON-RPC Server could return non-200 on error
|
||||
error : function(jqXHR, textStatus, errorThrown) {
|
||||
try {
|
||||
var response = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if ('console' in window) console.log(response);
|
||||
|
||||
error_cb(response.error, this);
|
||||
} catch (err) {
|
||||
// Perhaps the responseText wasn't really a jsonrpc-error.
|
||||
error_cb({ error: jqXHR.responseText }, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify sends a command to the server that won't need a response. In http, there is probably
|
||||
* an empty response - that will be dropped, but in ws there should be no response at all.
|
||||
*
|
||||
* This is very similar to call, but has no id and no handling of callbacks.
|
||||
*
|
||||
* @fn notify
|
||||
* @memberof $.JsonRpcClient
|
||||
*
|
||||
* @param method The method to run on JSON-RPC server.
|
||||
* @param params The params; an array or object.
|
||||
*/
|
||||
$.JsonRpcClient.prototype.notify = function(method, params) {
|
||||
// Construct the JSON-RPC 2.0 request.
|
||||
|
||||
if (this.options.sessid) {
|
||||
params.sessid = this.options.sessid;
|
||||
}
|
||||
|
||||
var request = {
|
||||
jsonrpc: '2.0',
|
||||
method: method,
|
||||
params: params
|
||||
};
|
||||
|
||||
// Try making a WebSocket call.
|
||||
var socket = this.options.getSocket(this.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
this._wsCall(socket, request);
|
||||
return;
|
||||
}
|
||||
|
||||
// No WebSocket, and no HTTP backend? This won't work.
|
||||
if (this.options.ajaxUrl === null) {
|
||||
throw "$.JsonRpcClient.notify used with no websocket and no http endpoint.";
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : this.options.ajaxUrl,
|
||||
data : $.toJSON(request),
|
||||
dataType : 'json',
|
||||
cache : false
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a batch-call by using a callback.
|
||||
*
|
||||
* The callback will get an object "batch" as only argument. On batch, you can call the methods
|
||||
* "call" and "notify" just as if it was a normal $.JsonRpcClient object, and all calls will be
|
||||
* sent as a batch call then the callback is done.
|
||||
*
|
||||
* @fn batch
|
||||
* @memberof $.JsonRpcClient
|
||||
*
|
||||
* @param callback The main function which will get a batch handler to run call and notify on.
|
||||
* @param all_done_cb A callback function to call after all results have been handled.
|
||||
* @param error_cb A callback function to call if there is an error from the server.
|
||||
* Note, that batch calls should always get an overall success, and the
|
||||
* only error
|
||||
*/
|
||||
$.JsonRpcClient.prototype.batch = function(callback, all_done_cb, error_cb) {
|
||||
var batch = new $.JsonRpcClient._batchObject(this, all_done_cb, error_cb);
|
||||
callback(batch);
|
||||
batch._execute();
|
||||
};
|
||||
|
||||
/**
|
||||
* The default getSocket handler.
|
||||
*
|
||||
* @param onmessage_cb The callback to be bound to onmessage events on the socket.
|
||||
*
|
||||
* @fn _getSocket
|
||||
* @memberof $.JsonRpcClient
|
||||
*/
|
||||
|
||||
$.JsonRpcClient.prototype.socketReady = function() {
|
||||
if (this._ws_socket === null || this._ws_socket.readyState > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$.JsonRpcClient.prototype.closeSocket = function() {
|
||||
var self = this;
|
||||
if (self.socketReady()) {
|
||||
self._ws_socket.onclose = function (w) {console.log("Closing Socket");};
|
||||
self._ws_socket.close();
|
||||
}
|
||||
};
|
||||
|
||||
$.JsonRpcClient.prototype.loginData = function(params) {
|
||||
var self = this;
|
||||
self.options.login = params.login;
|
||||
self.options.passwd = params.passwd;
|
||||
self.options.loginParams = params.loginParams;
|
||||
self.options.userVariables = params.userVariables;
|
||||
};
|
||||
|
||||
$.JsonRpcClient.prototype.connectSocket = function(onmessage_cb) {
|
||||
var self = this;
|
||||
|
||||
if (self.to) {
|
||||
clearTimeout(self.to);
|
||||
}
|
||||
|
||||
if (!self.socketReady()) {
|
||||
self.authing = false;
|
||||
|
||||
if (self._ws_socket) {
|
||||
delete self._ws_socket;
|
||||
}
|
||||
|
||||
// No socket, or dying socket, let's get a new one.
|
||||
self._ws_socket = new WebSocket(self.options.socketUrl);
|
||||
|
||||
if (self._ws_socket) {
|
||||
// Set up onmessage handler.
|
||||
self._ws_socket.onmessage = onmessage_cb;
|
||||
self._ws_socket.onclose = function (w) {
|
||||
if (!self.ws_sleep) {
|
||||
self.ws_sleep = 1000;
|
||||
}
|
||||
|
||||
if (self.options.onWSClose) {
|
||||
self.options.onWSClose(self);
|
||||
}
|
||||
|
||||
console.error("Websocket Lost " + self.ws_cnt + " sleep: " + self.ws_sleep + "msec");
|
||||
|
||||
self.to = setTimeout(function() {
|
||||
console.log("Attempting Reconnection....");
|
||||
self.connectSocket(onmessage_cb);
|
||||
}, self.ws_sleep);
|
||||
|
||||
self.ws_cnt++;
|
||||
|
||||
if (self.ws_sleep < 3000 && (self.ws_cnt % 10) === 0) {
|
||||
self.ws_sleep += 1000;
|
||||
}
|
||||
};
|
||||
|
||||
// Set up sending of message for when the socket is open.
|
||||
self._ws_socket.onopen = function() {
|
||||
if (self.to) {
|
||||
clearTimeout(self.to);
|
||||
}
|
||||
self.ws_sleep = 1000;
|
||||
self.ws_cnt = 0;
|
||||
if (self.options.onWSConnect) {
|
||||
self.options.onWSConnect(self);
|
||||
}
|
||||
|
||||
var req;
|
||||
// Send the requests.
|
||||
while ((req = $.JsonRpcClient.q.pop())) {
|
||||
self._ws_socket.send(req);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return self._ws_socket ? true : false;
|
||||
};
|
||||
|
||||
$.JsonRpcClient.prototype._getSocket = function(onmessage_cb) {
|
||||
// If there is no ws url set, we don't have a socket.
|
||||
// Likewise, if there is no window.WebSocket.
|
||||
if (this.options.socketUrl === null || !("WebSocket" in window)) return null;
|
||||
|
||||
this.connectSocket(onmessage_cb);
|
||||
|
||||
return this._ws_socket;
|
||||
};
|
||||
|
||||
/**
|
||||
* Queue to save messages delivered when websocket is not ready
|
||||
*/
|
||||
$.JsonRpcClient.q = [];
|
||||
|
||||
/**
|
||||
* Internal handler to dispatch a JRON-RPC request through a websocket.
|
||||
*
|
||||
* @fn _wsCall
|
||||
* @memberof $.JsonRpcClient
|
||||
*/
|
||||
$.JsonRpcClient.prototype._wsCall = function(socket, request, success_cb, error_cb) {
|
||||
var request_json = $.toJSON(request);
|
||||
|
||||
if (socket.readyState < 1) {
|
||||
// The websocket is not open yet; we have to set sending of the message in onopen.
|
||||
self = this; // In closure below, this is set to the WebSocket. Use self instead.
|
||||
$.JsonRpcClient.q.push(request_json);
|
||||
} else {
|
||||
// We have a socket and it should be ready to send on.
|
||||
socket.send(request_json);
|
||||
}
|
||||
|
||||
// Setup callbacks. If there is an id, this is a call and not a notify.
|
||||
if ('id' in request && typeof success_cb !== 'undefined') {
|
||||
this._ws_callbacks[request.id] = { request: request_json, request_obj: request, success_cb: success_cb, error_cb: error_cb };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal handler for the websocket messages. It determines if the message is a JSON-RPC
|
||||
* response, and if so, tries to couple it with a given callback. Otherwise, it falls back to
|
||||
* given external onmessage-handler, if any.
|
||||
*
|
||||
* @param event The websocket onmessage-event.
|
||||
*/
|
||||
$.JsonRpcClient.prototype._wsOnMessage = function(event) {
|
||||
// Check if this could be a JSON RPC message.
|
||||
var response;
|
||||
|
||||
// Special sub proto
|
||||
if (event.data[0] == "#" && event.data[1] == "S" && event.data[2] == "P") {
|
||||
if (event.data[3] == "U") {
|
||||
this.up_dur = parseInt(event.data.substring(4));
|
||||
} else if (this.speedCB && event.data[3] == "D") {
|
||||
this.down_dur = parseInt(event.data.substring(4));
|
||||
|
||||
var up_kps = (((this.speedBytes * 8) / (this.up_dur / 1000)) / 1024).toFixed(0);
|
||||
var down_kps = (((this.speedBytes * 8) / (this.down_dur / 1000)) / 1024).toFixed(0);
|
||||
|
||||
console.info("Speed Test: Up: " + up_kps + " Down: " + down_kps);
|
||||
this.speedCB(event, { upDur: this.up_dur, downDur: this.down_dur, upKPS: up_kps, downKPS: down_kps });
|
||||
this.speedCB = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
response = $.parseJSON(event.data);
|
||||
|
||||
/// @todo Make using the jsonrcp 2.0 check optional, to use this on JSON-RPC 1 backends.
|
||||
|
||||
if (typeof response === 'object' &&
|
||||
'jsonrpc' in response &&
|
||||
response.jsonrpc === '2.0') {
|
||||
|
||||
/// @todo Handle bad response (without id).
|
||||
|
||||
// If this is an object with result, it is a response.
|
||||
if ('result' in response && this._ws_callbacks[response.id]) {
|
||||
// Get the success callback.
|
||||
var success_cb = this._ws_callbacks[response.id].success_cb;
|
||||
|
||||
/*
|
||||
// set the sessid if present
|
||||
if ('sessid' in response.result && !this.options.sessid || (this.options.sessid != response.result.sessid)) {
|
||||
this.options.sessid = response.result.sessid;
|
||||
if (this.options.sessid) {
|
||||
console.log("setting session UUID to: " + this.options.sessid);
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Delete the callback from the storage.
|
||||
delete this._ws_callbacks[response.id];
|
||||
|
||||
// Run callback with result as parameter.
|
||||
success_cb(response.result, this);
|
||||
return;
|
||||
} else if ('error' in response && this._ws_callbacks[response.id]) {
|
||||
// If this is an object with error, it is an error response.
|
||||
|
||||
// Get the error callback.
|
||||
var error_cb = this._ws_callbacks[response.id].error_cb;
|
||||
var orig_req = this._ws_callbacks[response.id].request;
|
||||
|
||||
// if this is an auth request, send the credentials and resend the failed request
|
||||
if (!self.authing && response.error.code == -32000 && self.options.login && self.options.passwd) {
|
||||
self.authing = true;
|
||||
|
||||
this.call("login", { login: self.options.login, passwd: self.options.passwd, loginParams: self.options.loginParams,
|
||||
userVariables: self.options.userVariables},
|
||||
this._ws_callbacks[response.id].request_obj.method == "login" ?
|
||||
function(e) {
|
||||
self.authing = false;
|
||||
console.log("logged in");
|
||||
delete self._ws_callbacks[response.id];
|
||||
|
||||
if (self.options.onWSLogin) {
|
||||
self.options.onWSLogin(true, self);
|
||||
}
|
||||
}
|
||||
|
||||
:
|
||||
|
||||
function(e) {
|
||||
self.authing = false;
|
||||
console.log("logged in, resending request id: " + response.id);
|
||||
var socket = self.options.getSocket(self.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
socket.send(orig_req);
|
||||
}
|
||||
if (self.options.onWSLogin) {
|
||||
self.options.onWSLogin(true, self);
|
||||
}
|
||||
},
|
||||
|
||||
function(e) {
|
||||
console.log("error logging in, request id:", response.id);
|
||||
delete self._ws_callbacks[response.id];
|
||||
error_cb(response.error, this);
|
||||
if (self.options.onWSLogin) {
|
||||
self.options.onWSLogin(false, self);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete the callback from the storage.
|
||||
delete this._ws_callbacks[response.id];
|
||||
|
||||
// Run callback with the error object as parameter.
|
||||
error_cb(response.error, this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Probably an error while parsing a non json-string as json. All real JSON-RPC cases are
|
||||
// handled above, and the fallback method is called below.
|
||||
console.log("ERROR: "+ err);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is not a JSON-RPC response. Call the fallback message handler, if given.
|
||||
if (typeof this.options.onmessage === 'function') {
|
||||
event.eventData = response;
|
||||
if (!event.eventData) {
|
||||
event.eventData = {};
|
||||
}
|
||||
|
||||
var reply = this.options.onmessage(event);
|
||||
|
||||
if (reply && typeof reply === "object" && event.eventData.id) {
|
||||
var msg = {
|
||||
jsonrpc: "2.0",
|
||||
id: event.eventData.id,
|
||||
result: reply
|
||||
};
|
||||
|
||||
var socket = self.options.getSocket(self.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
socket.send($.toJSON(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************************************
|
||||
* Batch object with methods
|
||||
************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Handling object for batch calls.
|
||||
*/
|
||||
$.JsonRpcClient._batchObject = function(jsonrpcclient, all_done_cb, error_cb) {
|
||||
// Array of objects to hold the call and notify requests. Each objects will have the request
|
||||
// object, and unless it is a notify, success_cb and error_cb.
|
||||
this._requests = [];
|
||||
|
||||
this.jsonrpcclient = jsonrpcclient;
|
||||
this.all_done_cb = all_done_cb;
|
||||
this.error_cb = typeof error_cb === 'function' ? error_cb : function() {};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @sa $.JsonRpcClient.prototype.call
|
||||
*/
|
||||
$.JsonRpcClient._batchObject.prototype.call = function(method, params, success_cb, error_cb) {
|
||||
|
||||
if (!params) {
|
||||
params = {};
|
||||
}
|
||||
|
||||
if (this.options.sessid) {
|
||||
params.sessid = this.options.sessid;
|
||||
}
|
||||
|
||||
if (!success_cb) {
|
||||
success_cb = function(e){console.log("Success: ", e);};
|
||||
}
|
||||
|
||||
if (!error_cb) {
|
||||
error_cb = function(e){console.log("Error: ", e);};
|
||||
}
|
||||
|
||||
this._requests.push({
|
||||
request : {
|
||||
jsonrpc : '2.0',
|
||||
method : method,
|
||||
params : params,
|
||||
id : this.jsonrpcclient._current_id++ // Use the client's id series.
|
||||
},
|
||||
success_cb : success_cb,
|
||||
error_cb : error_cb
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @sa $.JsonRpcClient.prototype.notify
|
||||
*/
|
||||
$.JsonRpcClient._batchObject.prototype.notify = function(method, params) {
|
||||
if (this.options.sessid) {
|
||||
params.sessid = this.options.sessid;
|
||||
}
|
||||
|
||||
this._requests.push({
|
||||
request : {
|
||||
jsonrpc : '2.0',
|
||||
method : method,
|
||||
params : params
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes the batched up calls.
|
||||
*/
|
||||
$.JsonRpcClient._batchObject.prototype._execute = function() {
|
||||
var self = this;
|
||||
|
||||
if (this._requests.length === 0) return; // All done :P
|
||||
|
||||
// Collect all request data and sort handlers by request id.
|
||||
var batch_request = [];
|
||||
var handlers = {};
|
||||
var i = 0;
|
||||
var call;
|
||||
var success_cb;
|
||||
var error_cb;
|
||||
|
||||
// If we have a WebSocket, just send the requests individually like normal calls.
|
||||
var socket = self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);
|
||||
if (socket !== null) {
|
||||
for (i = 0; i < this._requests.length; i++) {
|
||||
call = this._requests[i];
|
||||
success_cb = ('success_cb' in call) ? call.success_cb : undefined;
|
||||
error_cb = ('error_cb' in call) ? call.error_cb : undefined;
|
||||
self.jsonrpcclient._wsCall(socket, call.request, success_cb, error_cb);
|
||||
}
|
||||
|
||||
if (typeof all_done_cb === 'function') all_done_cb(result);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < this._requests.length; i++) {
|
||||
call = this._requests[i];
|
||||
batch_request.push(call.request);
|
||||
|
||||
// If the request has an id, it should handle returns (otherwise it's a notify).
|
||||
if ('id' in call.request) {
|
||||
handlers[call.request.id] = {
|
||||
success_cb : call.success_cb,
|
||||
error_cb : call.error_cb
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
success_cb = function(data) { self._batchCb(data, handlers, self.all_done_cb); };
|
||||
|
||||
// No WebSocket, and no HTTP backend? This won't work.
|
||||
if (self.jsonrpcclient.options.ajaxUrl === null) {
|
||||
throw "$.JsonRpcClient.batch used with no websocket and no http endpoint.";
|
||||
}
|
||||
|
||||
// Send request
|
||||
$.ajax({
|
||||
url : self.jsonrpcclient.options.ajaxUrl,
|
||||
data : $.toJSON(batch_request),
|
||||
dataType : 'json',
|
||||
cache : false,
|
||||
type : 'POST',
|
||||
|
||||
// Batch-requests should always return 200
|
||||
error : function(jqXHR, textStatus, errorThrown) {
|
||||
self.error_cb(jqXHR, textStatus, errorThrown);
|
||||
},
|
||||
success : success_cb
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal helper to match the result array from a batch call to their respective callbacks.
|
||||
*
|
||||
* @fn _batchCb
|
||||
* @memberof $.JsonRpcClient
|
||||
*/
|
||||
$.JsonRpcClient._batchObject.prototype._batchCb = function(result, handlers, all_done_cb) {
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var response = result[i];
|
||||
|
||||
// Handle error
|
||||
if ('error' in response) {
|
||||
if (response.id === null || !(response.id in handlers)) {
|
||||
// An error on a notify? Just log it to the console.
|
||||
if ('console' in window) console.log(response);
|
||||
} else {
|
||||
handlers[response.id].error_cb(response.error, this);
|
||||
}
|
||||
} else {
|
||||
// Here we should always have a correct id and no error.
|
||||
if (!(response.id in handlers) && 'console' in window) {
|
||||
console.log(response);
|
||||
} else {
|
||||
handlers[response.id].success_cb(response.result, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof all_done_cb === 'function') all_done_cb(result);
|
||||
};
|
||||
|
||||
})(jQuery);
|
10
clients/flash/web-client/src/main/resources/lib/jquery.mobile.min.js
vendored
Executable file
10
clients/flash/web-client/src/main/resources/lib/jquery.mobile.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
2729
clients/flash/web-client/src/main/resources/lib/jquery.verto.js
Executable file
2729
clients/flash/web-client/src/main/resources/lib/jquery.verto.js
Executable file
File diff suppressed because it is too large
Load Diff
16
clients/flash/web-client/src/main/resources/lib/jsnlog.min.js
vendored
Executable file
16
clients/flash/web-client/src/main/resources/lib/jsnlog.min.js
vendored
Executable file
@ -0,0 +1,16 @@
|
||||
var __extends=this.__extends||function(b,d){function n(){this.constructor=b}for(var f in d)d.hasOwnProperty(f)&&(b[f]=d[f]);n.prototype=d.prototype;b.prototype=new n};
|
||||
function JL(b){if(!b)return JL.__;Array.prototype.reduce||(Array.prototype.reduce=function(b,d){for(var l=d,g=0;g<this.length;g++)l=b(l,this[g],g,this);return l});var d="";return("."+b).split(".").reduce(function(b,f,l,g){d=d?d+("."+f):f;f=b["__"+d];void 0===f&&(JL.Logger.prototype=b,f=new JL.Logger(d),b["__"+d]=f);return f},JL.__)}
|
||||
(function(b){function d(a,c,h){void 0!==c[a]&&(null===c[a]?delete h[a]:h[a]=c[a])}function n(a){if(null!=b.enabled&&!b.enabled||null!=b.maxMessages&&1>b.maxMessages)return!1;try{if(a.userAgentRegex&&!RegExp(a.userAgentRegex).test(navigator.userAgent))return!1}catch(c){}try{if(a.ipRegex&&b.clientIP&&!RegExp(a.ipRegex).test(b.clientIP))return!1}catch(h){}return!0}function f(a,c){try{if(a.disallow&&RegExp(a.disallow).test(c))return!1}catch(h){}return!0}function l(a){return"function"==typeof a?a instanceof
|
||||
RegExp?a.toString():a():a}function g(a){a=l(a);switch(typeof a){case "string":return new m(a,null,a);case "number":return a=a.toString(),new m(a,null,a);case "boolean":return a=a.toString(),new m(a,null,a);case "undefined":return new m("undefined",null,"undefined");case "object":return a instanceof RegExp||a instanceof String||a instanceof Number||a instanceof Boolean?(a=a.toString(),new m(a,null,a)):new m(null,a,JSON.stringify(a));default:return new m("unknown",null,"unknown")}}b.enabled;b.maxMessages;
|
||||
b.defaultAjaxUrl;b.clientIP;b.defaultBeforeSend;b.requestId="";var m=function(){return function(a,c,h){this.msg=a;this.meta=c;this.finalString=h}}();b.setOptions=function(a){d("enabled",a,this);d("maxMessages",a,this);d("defaultAjaxUrl",a,this);d("clientIP",a,this);d("requestId",a,this);d("defaultBeforeSend",a,this);return this};b.getAllLevel=function(){return-2147483648};b.getTraceLevel=function(){return 1E3};b.getDebugLevel=function(){return 2E3};b.getInfoLevel=function(){return 3E3};b.getWarnLevel=
|
||||
function(){return 4E3};b.getErrorLevel=function(){return 5E3};b.getFatalLevel=function(){return 6E3};b.getOffLevel=function(){return 2147483647};var e=function(){return function(a,c){this.inner=c;this.name="JL.Exception";this.message=g(a).finalString}}();b.Exception=e;e.prototype=Error();var r=function(){return function(a,c,h,b){this.l=a;this.m=c;this.n=h;this.t=b}}();b.LogItem=r;e=function(){function a(c,a){this.appenderName=c;this.sendLogItems=a;this.level=b.getTraceLevel();this.sendWithBufferLevel=
|
||||
2147483647;this.storeInBufferLevel=-2147483648;this.bufferSize=0;this.batchSize=1;this.buffer=[];this.batchBuffer=[]}a.prototype.setOptions=function(c){d("level",c,this);d("ipRegex",c,this);d("userAgentRegex",c,this);d("disallow",c,this);d("sendWithBufferLevel",c,this);d("storeInBufferLevel",c,this);d("bufferSize",c,this);d("batchSize",c,this);this.bufferSize<this.buffer.length&&(this.buffer.length=this.bufferSize);return this};a.prototype.log=function(c,a,b,d,k,e,g){!n(this)||!f(this,e)||k<this.storeInBufferLevel||
|
||||
(c=new r(k,e,g,(new Date).getTime()),k<this.level?0<this.bufferSize&&(this.buffer.push(c),this.buffer.length>this.bufferSize&&this.buffer.shift()):(k<this.sendWithBufferLevel||!this.buffer.length||(this.batchBuffer=this.batchBuffer.concat(this.buffer),this.buffer.length=0),this.batchBuffer.push(c),this.batchBuffer.length>=this.batchSize&&this.sendBatch()))};a.prototype.sendBatch=function(){0==this.batchBuffer.length||null!=b.maxMessages&&1>b.maxMessages||(null!=b.maxMessages&&(b.maxMessages-=this.batchBuffer.length),
|
||||
this.sendLogItems(this.batchBuffer),this.batchBuffer.length=0)};return a}();b.Appender=e;var p=function(a){function c(b){a.call(this,b,c.prototype.sendLogItemsAjax)}__extends(c,a);c.prototype.setOptions=function(c){d("url",c,this);d("beforeSend",c,this);a.prototype.setOptions.call(this,c);return this};c.prototype.sendLogItemsAjax=function(c){try{var a="/jsnlog.logger";null!=b.defaultAjaxUrl&&(a=b.defaultAjaxUrl);this.url&&(a=this.url);var d=JSON.stringify({r:b.requestId,lg:c}),k=this.getXhr(a);"function"===
|
||||
typeof this.beforeSend?this.beforeSend(k):"function"===typeof b.defaultBeforeSend&&b.defaultBeforeSend(k);k.send(d)}catch(f){}};c.prototype.getXhr=function(c){var a=new XMLHttpRequest;if(!("withCredentials"in a)&&"undefined"!=typeof XDomainRequest)return a=new XDomainRequest,a.open("POST",c),a;a.open("POST",c);a.setRequestHeader("Content-Type","application/json");a.setRequestHeader("JSNLog-RequestId",b.requestId);return a};return c}(e);b.AjaxAppender=p;var q=function(a){function c(b){a.call(this,
|
||||
b,c.prototype.sendLogItemsConsole)}__extends(c,a);c.prototype.clog=function(a){console.log(a)};c.prototype.cerror=function(a){console.error?console.error(a):this.clog(a)};c.prototype.cwarn=function(a){console.warn?console.warn(a):this.clog(a)};c.prototype.cinfo=function(a){console.info?console.info(a):this.clog(a)};c.prototype.cdebug=function(a){console.debug?console.debug(a):this.cinfo(a)};c.prototype.sendLogItemsConsole=function(a){try{if(console){var c;for(c=0;c<a.length;++c){var d=a[c],f=d.n+
|
||||
": "+d.m;"undefined"===typeof window&&(f=new Date(d.t)+" | "+f);d.l<=b.getDebugLevel()?this.cdebug(f):d.l<=b.getInfoLevel()?this.cinfo(f):d.l<=b.getWarnLevel()?this.cwarn(f):this.cerror(f)}}}catch(e){}};return c}(e);b.ConsoleAppender=q;e=function(){function a(a){this.loggerName=a;this.seenRegexes=[]}a.prototype.setOptions=function(a){d("level",a,this);d("userAgentRegex",a,this);d("disallow",a,this);d("ipRegex",a,this);d("appenders",a,this);d("onceOnly",a,this);this.seenRegexes=[];return this};a.prototype.buildExceptionObject=
|
||||
function(a){var b={};a.stack?b.stack=a.stack:b.e=a;a.message&&(b.message=a.message);a.name&&(b.name=a.name);a.data&&(b.data=a.data);a.inner&&(b.inner=this.buildExceptionObject(a.inner));return b};a.prototype.log=function(a,b,d){var e=0;if(!this.appenders)return this;if(a>=this.level&&n(this)&&(d?(e=this.buildExceptionObject(d),e.logData=l(b)):e=b,b=g(e),f(this,b.finalString))){if(this.onceOnly)for(e=this.onceOnly.length-1;0<=e;){if(RegExp(this.onceOnly[e]).test(b.finalString)){if(this.seenRegexes[e])return this;
|
||||
this.seenRegexes[e]=!0}e--}b.meta=b.meta||{};b.meta.loggerName=this.loggerName;for(e=this.appenders.length-1;0<=e;)this.appenders[e].log(1E3>=a?"trace":2E3>=a?"debug":3E3>=a?"info":4E3>=a?"warn":5E3>=a?"error":"fatal",b.msg,b.meta,function(){},a,b.finalString,this.loggerName),e--}return this};a.prototype.trace=function(a){return this.log(1E3,a)};a.prototype.debug=function(a){return this.log(2E3,a)};a.prototype.info=function(a){return this.log(3E3,a)};a.prototype.warn=function(a){return this.log(4E3,
|
||||
a)};a.prototype.error=function(a){return this.log(5E3,a)};a.prototype.fatal=function(a){return this.log(6E3,a)};a.prototype.fatalException=function(a,b){return this.log(6E3,a,b)};return a}();b.Logger=e;b.createAjaxAppender=function(a){return new p(a)};b.createConsoleAppender=function(a){return new q(a)};e=new p("");"undefined"===typeof window&&(e=new q(""));b.__=new b.Logger("");b.__.setOptions({level:b.getDebugLevel(),appenders:[e]})})(JL||(JL={}));var exports;
|
||||
"undefined"!==typeof exports&&(exports.JL=JL);var define;"function"==typeof define&&define.amd&&define("jsnlog",[],function(){return JL});"function"==typeof __jsnlog_configure&&__jsnlog_configure(JL);
|
10979
clients/flash/web-client/src/main/resources/lib/sip.js
Executable file
10979
clients/flash/web-client/src/main/resources/lib/sip.js
Executable file
File diff suppressed because it is too large
Load Diff
404
clients/flash/web-client/src/main/resources/lib/verto_extension.js
Executable file
404
clients/flash/web-client/src/main/resources/lib/verto_extension.js
Executable file
@ -0,0 +1,404 @@
|
||||
var callback = function(message){console.log(message);}; // holds the user's callback for a global scope
|
||||
callbacks = {};
|
||||
var callICEConnected = false;
|
||||
var callPurposefullyEnded = false; // used to determine whether the user ended the call or the call was ended from somewhere else outside
|
||||
var callTimeout = null; // function that will run if there is no call established
|
||||
var toDisplayDisconnectCallback = true; // if a call is dropped only display the error the first time
|
||||
var wasCallSuccessful = false; // when the websocket connection is closed this determines whether a call was ever successfully established
|
||||
webcamStream = "webcamStream";
|
||||
window[webcamStream] = null;
|
||||
verto = null;
|
||||
videoTag = null;
|
||||
|
||||
// receives either a string variable holding the name of an actionscript
|
||||
// registered callback, or a javascript function object.
|
||||
// The function will return either the function if it is a javascript Function
|
||||
// or if it is an actionscript string it will return a javascript Function
|
||||
// that when invokved will invoke the actionscript registered callback
|
||||
// and passes along parameters
|
||||
function normalizeCallback(callback) {
|
||||
if (typeof callback == "function") {
|
||||
return callback;
|
||||
} else {
|
||||
return function(args) {
|
||||
document.getElementById("BigBlueButton")[callback](args);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// save a copy of the hangup function registered for the verto object
|
||||
var oldHangup = $.verto.prototype.hangup;
|
||||
// overwrite the verto hangup handler with my own handler
|
||||
$.verto.prototype.hangup = function(callID, userCallback) {
|
||||
console.log("call state callbacks - bye");
|
||||
if (userCallback) {
|
||||
callback = userCallback;
|
||||
}
|
||||
callActive = false;
|
||||
|
||||
if (cur_call) {
|
||||
console.log('call ended ' + cur_call.audioStream.currentTime); // the duration of the call
|
||||
if (callPurposefullyEnded === true) { // the user ended the call themself
|
||||
callback({'status':'ended'});
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': 1005}); // Call ended unexpectedly
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
cur_call = null;
|
||||
} else {
|
||||
console.log('bye event already received');
|
||||
}
|
||||
// call the original hangup procedure
|
||||
return oldHangup.apply(this, arguments);
|
||||
}
|
||||
|
||||
// main entry point to making a verto call
|
||||
callIntoConference_verto = function(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, videoTag, options, vertoServerCredentials) {
|
||||
window.videoTag = videoTag;
|
||||
// stores the user's callback in the global scope
|
||||
if (userCallback) {
|
||||
callback = userCallback;
|
||||
}
|
||||
if(!isLoggedIntoVerto()) { // start the verto log in procedure
|
||||
// runs when a web socket is disconnected
|
||||
callbacks.onWSClose = function(v, success) {
|
||||
if(wasCallSuccessful) { // a call was established through the websocket
|
||||
if(toDisplayDisconnectCallback) { // will only display the error the first time
|
||||
// the connection was dropped in an already established call
|
||||
console.log("websocket disconnected");
|
||||
callback({'status':'failed', 'errorcode': 1001}); // WebSocket disconnected
|
||||
toDisplayDisconnectCallback = false;
|
||||
}
|
||||
} else {
|
||||
// this callback was triggered and a call was never successfully established
|
||||
console.log("websocket connection could not be established");
|
||||
callback({'status':'failed', 'errorcode': 1002}); // Could not make a WebSocket connection
|
||||
}
|
||||
}
|
||||
// runs when the websocket is successfully created
|
||||
callbacks.onWSLogin = function(v, success) {
|
||||
cur_call = null;
|
||||
ringing = false;
|
||||
console.log("Inside onWSLogin");
|
||||
|
||||
if (success) {
|
||||
console.log("starting call");
|
||||
toDisplayDisconnectCallback = true; // yes, display an error if the socket closes
|
||||
wasCallSuccessful = true; // yes, a call was successfully established through the websocket
|
||||
webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, options);
|
||||
} else {
|
||||
callback({'status':'failed', 'errorcode': '10XX'}); // eror logging verto into freeswitch
|
||||
}
|
||||
}
|
||||
// set up verto
|
||||
// $.verto.init({}, init(videoTag));
|
||||
init(videoTag, vertoServerCredentials);
|
||||
} else {
|
||||
console.log("already logged into verto, going straight to making a call");
|
||||
webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, options);
|
||||
}
|
||||
}
|
||||
|
||||
checkSupport = function(callback) {
|
||||
if(!isWebRTCAvailable_verto()) {
|
||||
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
|
||||
}
|
||||
|
||||
if (!navigator.getUserMedia) {
|
||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
}
|
||||
|
||||
if (!navigator.getUserMedia){
|
||||
callback({'status': 'failed', 'errorcode': '10XX'}); // getUserMedia not supported in this browser
|
||||
}
|
||||
}
|
||||
|
||||
configStuns = function(callbacks, callback, videoTag, vertoServerCredentials) {
|
||||
console.log("Fetching STUN/TURN server info for Verto initialization");
|
||||
var stunsConfig = {};
|
||||
$.ajax({
|
||||
dataType: 'json',
|
||||
url: '/bigbluebutton/api/stuns/'
|
||||
}).done(function(data) {
|
||||
console.log("ajax request done");
|
||||
console.log(data);
|
||||
if(data['response'] && data.response.returncode == "FAILED") {
|
||||
console.error(data.response.message);
|
||||
callback({'status':'failed', 'errorcode': data.response.message});
|
||||
return;
|
||||
}
|
||||
stunsConfig['stunServers'] = ( data['stunServers'] ? data['stunServers'].map(function(data) {
|
||||
return {'url': data['url']};
|
||||
}) : [] );
|
||||
stunsConfig['turnServers'] = ( data['turnServers'] ? data['turnServers'].map(function(data) {
|
||||
return {
|
||||
'urls': data['url'],
|
||||
'username': data['username'],
|
||||
'credential': data['password']
|
||||
};
|
||||
}) : [] );
|
||||
stunsConfig = stunsConfig['stunServers'].concat(stunsConfig['turnServers']);
|
||||
console.log("success got stun data, making verto");
|
||||
makeVerto(callbacks, stunsConfig, videoTag, vertoServerCredentials);
|
||||
}).fail(function(data, textStatus, errorThrown) {
|
||||
// BBBLog.error("Could not fetch stun/turn servers", {error: textStatus, user: callerIdName, voiceBridge: conferenceVoiceBridge});
|
||||
callback({'status':'failed', 'errorcode': 1009});
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
docall_verto = function(extension, conferenceUsername, conferenceIdNumber, callbacks, options) {
|
||||
console.log(extension + ", " + conferenceUsername + ", " + conferenceIdNumber);
|
||||
|
||||
if (cur_call) { // only allow for one call
|
||||
console.log("Quitting: Call already in progress");
|
||||
return;
|
||||
}
|
||||
// determine the resolution the user chose for webcam video
|
||||
my_check_vid_res();
|
||||
outgoingBandwidth = "default";
|
||||
incomingBandwidth = "default";
|
||||
var useVideo = useCamera = useMic = false;
|
||||
// debugger;
|
||||
if(options.watchOnly) {
|
||||
window.watchOnly = true;
|
||||
window.listenOnly = false;
|
||||
window.joinAudio = false;
|
||||
useVideo = true;
|
||||
useCamera = false;
|
||||
useMic = false;
|
||||
} else if(options.listenOnly) {
|
||||
window.listenOnly = true;
|
||||
window.watchOnly = false;
|
||||
window.joinAudio = false;
|
||||
useVideo = false;
|
||||
useCamera = false;
|
||||
useMic = false;
|
||||
} else if(options.joinAudio) {
|
||||
window.joinAudio = true;
|
||||
window.watchOnly = false;
|
||||
window.listenOnly = false;
|
||||
useVideo = false;
|
||||
useCamera = false;
|
||||
useMic = true;
|
||||
}
|
||||
|
||||
cur_call = verto.newCall({
|
||||
destination_number: extension,
|
||||
caller_id_name: conferenceUsername,
|
||||
caller_id_number: conferenceIdNumber,
|
||||
outgoingBandwidth: outgoingBandwidth,
|
||||
incomingBandwidth: incomingBandwidth,
|
||||
useStereo: true,
|
||||
useVideo: useVideo,
|
||||
useCamera: useCamera,
|
||||
useMic: useMic,
|
||||
dedEnc: false,
|
||||
mirrorInput: false
|
||||
});
|
||||
|
||||
if (callbacks != null) { // add user supplied callbacks to the current call
|
||||
cur_call.rtc.options.callbacks = $.extend(cur_call.rtc.options.callbacks, callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
// check if logged into verto by seeing if there is a ready websocket connection
|
||||
function isLoggedIntoVerto() {
|
||||
return (verto != null ? (ref = verto.rpcClient) != null ? ref.socketReady() : void 0 : void 0);
|
||||
}
|
||||
|
||||
// overwrite and substitute my own init function
|
||||
init = function(videoTag, vertoServerCredentials) {
|
||||
videoTag = window.videoTag;
|
||||
cur_call = null;
|
||||
share_call = null;
|
||||
incomingBandwidth = "default";
|
||||
configStuns(callbacks, callback, videoTag, vertoServerCredentials);
|
||||
}
|
||||
|
||||
// checks whether Google Chrome or Firefox have the WebRTCPeerConnection object
|
||||
function isWebRTCAvailable_verto() {
|
||||
return (typeof window.webkitRTCPeerConnection !== 'undefined' || typeof window.mozRTCPeerConnection !== 'undefined');
|
||||
}
|
||||
|
||||
// exit point for conference
|
||||
function leaveWebRTCVoiceConference_verto() {
|
||||
console.log("Leaving the voice conference");
|
||||
webrtc_hangup_verto();
|
||||
}
|
||||
|
||||
function make_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, server, recall, options) {
|
||||
if (userCallback) {
|
||||
callback = userCallback;
|
||||
}
|
||||
callPurposefullyEnded = false;
|
||||
|
||||
// after 15 seconds if a call hasn't been established display error, hangup and logout of verto
|
||||
callTimeout = setTimeout(function() {
|
||||
console.log('Ten seconds without updates sending timeout code');
|
||||
callback({'status':'failed', 'errorcode': 1006}); // Failure on call
|
||||
if (verto != null) {
|
||||
verto.hangup();
|
||||
verto.logout();
|
||||
verto = null;
|
||||
}
|
||||
cur_call = null;
|
||||
}, 10000*1.5);
|
||||
|
||||
var myRTCCallbacks = {
|
||||
onError: function(vertoErrorObject, errorMessage) {
|
||||
console.error("custom callback: onError");
|
||||
console.error(vertoErrorObject);
|
||||
console.error("ERROR:");
|
||||
console.error(errorMessage);
|
||||
if(errorMessage.name === "PermissionDeniedError") { // user denied access to media peripherals
|
||||
console.error("User denied permission/access to hardware");
|
||||
console.error("getUserMedia: failure - ", errorMessage);
|
||||
callback({'status': 'mediafail', 'cause': errorMessage});
|
||||
}
|
||||
cur_call.hangup({cause: "Device or Permission Error"});
|
||||
clearTimeout(callTimeout);
|
||||
},
|
||||
onICEComplete: function(self, candidate) { // ICE candidate negotiation is complete
|
||||
console.log("custom callback: onICEComplete");
|
||||
console.log('Received ICE status changed to completed');
|
||||
if (callICEConnected === false) {
|
||||
callICEConnected = true;
|
||||
if (callActive === true) {
|
||||
callback({'status':'started'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
},
|
||||
onStream: function(rtc, stream) { // call has been established
|
||||
console.log("getUserMicMedia: success");
|
||||
callback({'status':'mediasuccess'});
|
||||
console.log("custom callback: stream started");
|
||||
callActive = true;
|
||||
console.log('BigBlueButton call accepted');
|
||||
|
||||
if (callICEConnected === true) {
|
||||
callback({'status':'started'});
|
||||
} else {
|
||||
callback({'status':'waitingforice'});
|
||||
}
|
||||
clearTimeout(callTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
if(isLoggedIntoVerto()) {
|
||||
console.log("Verto is logged into FreeSWITCH, socket is available, making call");
|
||||
callICEConnected = false;
|
||||
|
||||
docall_verto(voiceBridge, conferenceUsername, conferenceIdNumber, myRTCCallbacks, options);
|
||||
|
||||
if(recall === false) {
|
||||
console.log('call connecting');
|
||||
callback({'status': 'connecting'});
|
||||
} else {
|
||||
console.log('call connecting again');
|
||||
}
|
||||
|
||||
callback({'status':'mediarequest'});
|
||||
} else {
|
||||
console.error("Verto is NOT logged into FreeSWITCH, socket is NOT available, abandoning call request");
|
||||
}
|
||||
}
|
||||
|
||||
function makeVerto(callbacks, stunsConfig, videoTag, vertoServerCredentials) {
|
||||
var vertoPort = vertoServerCredentials.vertoPort;
|
||||
var hostName = vertoServerCredentials.hostName;
|
||||
var socketUrl = "wss://" + hostName + ":" + vertoPort;
|
||||
var login = vertoServerCredentials.login;
|
||||
var password = vertoServerCredentials.password;
|
||||
var minWidth = "640";
|
||||
var minHeight = "480";
|
||||
var maxWidth = "1920";
|
||||
var maxHeight = "1080";
|
||||
|
||||
console.log("stuns info is");
|
||||
console.log(stunsConfig);
|
||||
// debugger;
|
||||
verto = new $.verto({
|
||||
login: login,
|
||||
passwd: password,
|
||||
socketUrl: socketUrl,
|
||||
tag: videoTag,
|
||||
ringFile: "sounds/bell_ring2.wav",
|
||||
loginParams: {foo: true, bar: "yes"},
|
||||
useVideo: false,
|
||||
useCamera: false,
|
||||
iceServers: stunsConfig, // use user supplied stun configuration
|
||||
// iceServers: true, // use stun, use default verto configuration
|
||||
}, callbacks);
|
||||
}
|
||||
|
||||
// sets verto to begin using the resolution that the user selected
|
||||
my_check_vid_res = function() {
|
||||
var selectedVideoConstraints = getChosenWebcamResolution();
|
||||
my_real_size(selectedVideoConstraints);
|
||||
|
||||
if (verto) {
|
||||
verto.videoParams({
|
||||
"minWidth": selectedVideoConstraints.constraints.minWidth,
|
||||
"minHeight": selectedVideoConstraints.constraints.minHeight,
|
||||
"maxWidth": selectedVideoConstraints.constraints.maxWidth,
|
||||
"maxHeight": selectedVideoConstraints.constraints.maxHeight,
|
||||
"minFrameRate": selectedVideoConstraints.constraints.minFrameRate,
|
||||
"vertoBestFrameRate": selectedVideoConstraints.constraints.vertoBestFrameRate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
my_real_size = function(selectedVideoConstraints) {
|
||||
$("#" + window.videoTag).height("100%");
|
||||
$("#" + window.videoTag).width("100%");
|
||||
}
|
||||
|
||||
var RTCPeerConnectionCallbacks = {
|
||||
iceFailed: function(e) {
|
||||
console.log('received ice negotiation failed');
|
||||
callback({'status':'failed', 'errorcode': 1007}); // Failure on call
|
||||
//
|
||||
// TODO unless I do this, the call only lasts for a few seconds.
|
||||
// When I comment out the lines below, it works fine indefinitely
|
||||
// Anton Georgiev Dec 10 2015
|
||||
//
|
||||
//cur_call = null;
|
||||
//verto.hangup();
|
||||
//verto = null;
|
||||
//clearTimeout(callTimeout);
|
||||
}
|
||||
};
|
||||
this.RTCPeerConnectionCallbacks = RTCPeerConnectionCallbacks;
|
||||
|
||||
window.verto_afterStreamPublish = function() {}
|
||||
|
||||
function webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, options) {
|
||||
if (userCallback) {
|
||||
callback = userCallback;
|
||||
}
|
||||
console.log("webrtc_call\n"+voiceBridge + ", " + conferenceUsername + ", " + conferenceIdNumber + ", " + callback);
|
||||
|
||||
if(!isWebRTCAvailable()) {
|
||||
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
|
||||
return;
|
||||
}
|
||||
|
||||
var server = window.document.location.hostname;
|
||||
console.log("user " + conferenceUsername + " calling to " + voiceBridge);
|
||||
if (isLoggedIntoVerto()) {
|
||||
make_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, "", false, options);
|
||||
}
|
||||
}
|
||||
|
||||
function webrtc_hangup_verto(userCallback) {
|
||||
if (userCallback) {
|
||||
callback = userCallback;
|
||||
}
|
||||
callPurposefullyEnded = true;
|
||||
console.log("Hanging up current session");
|
||||
if(verto) {
|
||||
verto.hangup(false, callback);
|
||||
}
|
||||
}
|
214
clients/flash/web-client/src/main/resources/lib/verto_extension_share.js
Executable file
214
clients/flash/web-client/src/main/resources/lib/verto_extension_share.js
Executable file
@ -0,0 +1,214 @@
|
||||
var deskshareStream = "deskshareStream";
|
||||
window[deskshareStream] = null;
|
||||
this.share_call = null;
|
||||
|
||||
// final entry point for sharing from Chrome.
|
||||
// already have the resolution and constraints chosen
|
||||
var configDeskshareFromChrome = function(videoTag, callbacks, extensionId, resolutionConstruction) {
|
||||
// do initial check for extension
|
||||
getChromeExtensionStatus(extensionId, function(status) {
|
||||
if (status != "installed-enabled") {
|
||||
callbacks.onError({'status': 'failed', 'errorcode': 2001});
|
||||
console.error("No chrome Extension");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// bring up Chrome screen picker
|
||||
getScreenConstraints(function(error, screen_constraints) {
|
||||
if(error) {
|
||||
callbacks.onError({'status': 'failed', 'errorcode': 2021});
|
||||
return console.error(error);
|
||||
}
|
||||
|
||||
screen_constraints = resolutionConstruction(screen_constraints);
|
||||
window.firefoxDesksharePresent = false;
|
||||
doCall(screen_constraints, videoTag, callbacks);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// entry point for Chrome HTML5 sharing
|
||||
// connects with html5 client libraries to retrieve a selected resolution
|
||||
var configDeskshareFromChromeHTML5 = function(videoTag, callbacks, extensionId) {
|
||||
var resolutionConstruction = function(screen_constraints) {
|
||||
console.log("modifying video quality");
|
||||
var selectedDeskshareResolution = getChosenDeskshareResolution(); // this is the video profile the user chose
|
||||
my_real_size(selectedDeskshareResolution);
|
||||
var selectedDeskshareConstraints = getDeskshareConstraintsFromResolution(selectedDeskshareResolution, screen_constraints); // convert to a valid constraints object
|
||||
console.log(selectedDeskshareConstraints);
|
||||
return selectedDeskshareConstraints.video.mandatory;
|
||||
};
|
||||
configDeskshareFromChrome(videoTag, callbacks, extensionId, resolutionConstruction);
|
||||
};
|
||||
|
||||
// entry point when desksharing using Google Chrome via the flash Client
|
||||
// currently uses a default preset resolution in place of a resolution picker
|
||||
// prepares the constraints and passes off to generic Chrome handler
|
||||
var configDeskshareFromChromeFlash = function(videoTag, callbacks, extensionId) {
|
||||
var resolutionConstruction = function(screen_constraints) {
|
||||
// BigBlueButton low
|
||||
var getDeskshareConstraints = function(constraints) {
|
||||
return {
|
||||
"audio": false,
|
||||
"video": {
|
||||
"mandatory": {
|
||||
"maxWidth": 160,
|
||||
"maxHeight": 120,
|
||||
"chromeMediaSource": constraints.mandatory.chromeMediaSource,
|
||||
"chromeMediaSourceId": constraints.mandatory.chromeMediaSourceId,
|
||||
"minFrameRate": 10,
|
||||
},
|
||||
"optional": []
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
console.log("not modifying video quality");
|
||||
var selectedDeskshareConstraints = getDeskshareConstraints(screen_constraints); // convert to a valid constraints object
|
||||
console.log(selectedDeskshareConstraints);
|
||||
return selectedDeskshareConstraints.video.mandatory;
|
||||
};
|
||||
configDeskshareFromChrome(videoTag, callbacks, extensionId, resolutionConstruction);
|
||||
};
|
||||
|
||||
// final entry point for Firefox sharing
|
||||
var configDeskshareFromFirefox = function(screen_constraints, videoTag, callbacks) {
|
||||
// bypass all the default gUM calls inside jquery.FSRTC.js to use my own
|
||||
window.firefoxDesksharePresent = true;
|
||||
// the gUM args to invoke the Firefox screen picker
|
||||
var screen_constraints = {
|
||||
video: {
|
||||
"mozMediaSource": 'window',
|
||||
"mediaSource": 'window',
|
||||
}
|
||||
};
|
||||
// register the callback to the window namespace to be available in jquery.FSRTC.js
|
||||
window.firefoxDesksharePresentErrorCallback = callbacks.onError;
|
||||
doCall(screen_constraints, videoTag, callbacks);
|
||||
};
|
||||
|
||||
var configDeskshareFromFirefoxFlash = function(screen_constraints, videoTag, callbacks) {
|
||||
console.log("deskshare from firefox flash");
|
||||
configDeskshareFromFirefox(screen_constraints, videoTag, callbacks);
|
||||
};
|
||||
|
||||
var configDeskshareFromFirefoxHTML5 = function(screen_constraints, videoTag, callbacks) {
|
||||
console.log("deskshare from firefox html5");
|
||||
configDeskshareFromFirefox(screen_constraints, videoTag, callbacks);
|
||||
};
|
||||
|
||||
function endScreenshare(loggingCallback, onSuccess) {
|
||||
console.log("endScreenshare");
|
||||
if (share_call) {
|
||||
console.log("a screenshare call is active. Hanging up");
|
||||
share_call.hangup();
|
||||
share_call = null;
|
||||
normalizeCallback(onSuccess)();
|
||||
} else {
|
||||
console.log("a screenshare call is NOT active. Doing nothing");
|
||||
}
|
||||
normalizeCallback(loggingCallback)({'status':'success', 'message': 'screenshare ended'});
|
||||
}
|
||||
|
||||
function startScreenshare(loggingCallback, videoTag, vertoServerCredentials, extensionId, modifyResolution, onSuccess, onFail) {
|
||||
onSuccess = normalizeCallback(onSuccess);
|
||||
onFail = normalizeCallback(onFail);
|
||||
loggingCallback = normalizeCallback(loggingCallback);
|
||||
console.log("startScreenshare");
|
||||
if(!isLoggedIntoVerto()) { // start the verto log in procedure
|
||||
// runs when the websocket is successfully created
|
||||
callbacks.onWSLogin = function(v, success) {
|
||||
startScreenshareAfterLogin(loggingCallback, videoTag, extensionId, modifyResolution, onSuccess, onFail);
|
||||
loggingCallback({'status':'success', 'message': 'screenshare started'});
|
||||
console.log("logged in. starting screenshare");
|
||||
}
|
||||
// set up verto
|
||||
init(window.videoTag, vertoServerCredentials);
|
||||
} else {
|
||||
console.log("already logged into verto, going straight to making a call");
|
||||
startScreenshareAfterLogin(loggingCallback, videoTag, extensionId, modifyResolution, onSuccess, onFail);
|
||||
loggingCallback({'status':'success', 'message': 'screenshare started'});
|
||||
}
|
||||
}
|
||||
|
||||
function startScreenshareAfterLogin(loggingCallback, videoTag, extensionId, modifyResolution, onSuccess, onFail) {
|
||||
if (share_call) {
|
||||
return;
|
||||
}
|
||||
|
||||
outgoingBandwidth = incomingBandwidth = "default";
|
||||
var sharedev = "screen";
|
||||
|
||||
if (sharedev !== "screen") {
|
||||
console.log("Attempting Screen Capture with non-screen device....");
|
||||
|
||||
BBB.getMyUserInfo(function (retData){
|
||||
share_call = verto.newCall({
|
||||
destination_number: retData.voiceBridge + "-screen",
|
||||
caller_id_name: retData.myUsername + " (Screen)",
|
||||
caller_id_number: retData.myUserID + " (screen)",
|
||||
outgoingBandwidth: outgoingBandwidth,
|
||||
incomingBandwidth: incomingBandwidth,
|
||||
useCamera: sharedev,
|
||||
useVideo: true,
|
||||
screenShare: true,
|
||||
dedEnc: false,
|
||||
mirrorInput: false
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var callbacks = {
|
||||
onError: normalizeCallback(onFail),
|
||||
onICEComplete: function(self, candidate) { // ICE candidate negotiation is complete
|
||||
console.log("custom callback: onICEComplete");
|
||||
normalizeCallback(onSuccess)(candidate);
|
||||
}
|
||||
};
|
||||
|
||||
// determine if Firefox or Chrome
|
||||
// for now the only difference is that html5 has a resolution dialog
|
||||
if (!!navigator.mozGetUserMedia) {
|
||||
if (modifyResolution) {
|
||||
configDeskshareFromFirefoxHTML5(null, videoTag, callbacks);
|
||||
} else {
|
||||
configDeskshareFromFirefoxFlash(null, videoTag, callbacks);
|
||||
}
|
||||
} else if (!!window.chrome) {
|
||||
if (modifyResolution) {
|
||||
configDeskshareFromChromeHTML5(videoTag, callbacks, extensionId);
|
||||
} else {
|
||||
configDeskshareFromChromeFlash(videoTag, callbacks, extensionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doCall(screen_constraints, videoTag, callbacks) {
|
||||
console.log("\n\n\nhere are the screen_constraints\n\n\n");
|
||||
console.log(screen_constraints);
|
||||
window.listenOnly = false;
|
||||
window.watchOnly = false;
|
||||
window.joinAudio = true;
|
||||
|
||||
BBB.getMyUserInfo(function (retData){
|
||||
var callParams = {
|
||||
destination_number: retData.voiceBridge + "-screen",
|
||||
caller_id_name: retData.myUsername + " (Screen)",
|
||||
caller_id_number: retData.myUserID + " (screen)",
|
||||
outgoingBandwidth: outgoingBandwidth,
|
||||
incomingBandwidth: incomingBandwidth,
|
||||
videoParams: screen_constraints,
|
||||
useVideo: true,
|
||||
screenShare: true,
|
||||
dedEnc: true,
|
||||
mirrorInput: true,
|
||||
};
|
||||
|
||||
if (videoTag != null) {
|
||||
callParams.tag = videoTag;
|
||||
}
|
||||
share_call = verto.newCall(callParams);
|
||||
share_call.rtc.options.callbacks = $.extend(share_call.rtc.options.callbacks, callbacks);
|
||||
});
|
||||
}
|
105
clients/flash/web-client/src/main/resources/lib/weburl_regex.js
Executable file
105
clients/flash/web-client/src/main/resources/lib/weburl_regex.js
Executable file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// Regular Expression for URL validation
|
||||
//
|
||||
// Author: Diego Perini
|
||||
// Updated: 2010/12/05
|
||||
// License: MIT
|
||||
//
|
||||
// Copyright (c) 2010-2013 Diego Perini (http://www.iport.it)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the "Software"), to deal in the Software without
|
||||
// restriction, including without limitation the rights to use,
|
||||
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following
|
||||
// conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// the regular expression composed & commented
|
||||
// could be easily tweaked for RFC compliance,
|
||||
// it was expressly modified to fit & satisfy
|
||||
// these test for an URL shortener:
|
||||
//
|
||||
// http://mathiasbynens.be/demo/url-regex
|
||||
//
|
||||
// Notes on possible differences from a standard/generic validation:
|
||||
//
|
||||
// - utf-8 char class take in consideration the full Unicode range
|
||||
// - TLDs have been made mandatory so single names like "localhost" fails
|
||||
// - protocols have been restricted to ftp, http and https only as requested
|
||||
//
|
||||
// Changes:
|
||||
//
|
||||
// - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255
|
||||
// first and last IP address of each class is considered invalid
|
||||
// (since they are broadcast/network addresses)
|
||||
//
|
||||
// - Added exclusion of private, reserved and/or local networks ranges
|
||||
//
|
||||
// Compressed one-line versions:
|
||||
//
|
||||
// Javascript version
|
||||
//
|
||||
// /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/i
|
||||
//
|
||||
// PHP version
|
||||
//
|
||||
// _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/\S*)?$_iuS
|
||||
//
|
||||
var re_weburl = new RegExp(
|
||||
// protocol identifier
|
||||
"(?:(?:https?|ftp)://)" +
|
||||
// user:pass authentication
|
||||
"(?:\\S+(?::\\S*)?@)?" +
|
||||
"(?:" +
|
||||
// IP address exclusion
|
||||
// private & local networks
|
||||
"(?!(?:10|127)(?:\\.\\d{1,3}){3})" +
|
||||
"(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" +
|
||||
"(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
|
||||
// IP address dotted notation octets
|
||||
// excludes loopback network 0.0.0.0
|
||||
// excludes reserved space >= 224.0.0.0
|
||||
// excludes network & broacast addresses
|
||||
// (first & last IP address of each class)
|
||||
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
|
||||
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
|
||||
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
|
||||
"|" +
|
||||
// host name
|
||||
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" +
|
||||
// domain name
|
||||
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" +
|
||||
// TLD identifier
|
||||
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
|
||||
")" +
|
||||
// port number
|
||||
"(?::\\d{2,5})?" +
|
||||
// resource path
|
||||
"(?:/\\S*)?", "gi"
|
||||
);
|
||||
|
||||
function checkURLRegex(message) {
|
||||
return re_weburl.match(message);
|
||||
}
|
||||
|
||||
function parseURLs(message) {
|
||||
return String(message).replace(re_weburl, linkify);
|
||||
}
|
||||
|
||||
function linkify(match) {
|
||||
return '<a href="event:' + match + '"> <u>' + match + '</u></a>';
|
||||
}
|
54
clients/flash/web-client/src/main/resources/locales.xml
Executable file
54
clients/flash/web-client/src/main/resources/locales.xml
Executable file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" ?>
|
||||
<locales>
|
||||
<locale code="ar_SY" name="Arabic (Syria)"/>
|
||||
<locale code="az_AZ" name="Azerbaijani"/>
|
||||
<locale code="eu_EU" name="Basque" />
|
||||
<locale code="bn_BN" name="Bengali" />
|
||||
<locale code="bg_BG" name="Bulgarian" />
|
||||
<locale code="ca_ES" name="Catalan" />
|
||||
<locale code="zh_CN" name="Chinese (Simplified)"/>
|
||||
<locale code="zh_TW" name="Chinese (Traditional)"/>
|
||||
<locale code="hr_HR" name="Croatian" />
|
||||
<locale code="cs_CZ" name="Czech" />
|
||||
<locale code="da_DK" name="Danish" />
|
||||
<locale code="nl_NL" name="Dutch" />
|
||||
<locale code="en_US" name="English"/>
|
||||
<locale code="et_EE" name="Estonian"/>
|
||||
<locale code="fa_IR" name="Farsi" />
|
||||
<locale code="fi_FI" name="Finnish"/>
|
||||
<locale code="fr_FR" name="French"/>
|
||||
<locale code="fr_CA" name="French (Canadian)"/>
|
||||
<locale code="ff_SN" name="Fulah"/>
|
||||
<locale code="de_DE" name="German"/>
|
||||
<locale code="el_GR" name="Greek"/>
|
||||
<locale code="he_IL" name="Hebrew"/>
|
||||
<locale code="hu_HU" name="Hungarian"/>
|
||||
<locale code="id_ID" name="Indonesian"/>
|
||||
<locale code="it_IT" name="Italian"/>
|
||||
<locale code="ja_JP" name="Japanese"/>
|
||||
<locale code="ko_KR" name="Korean"/>
|
||||
<locale code="lv_LV" name="Latvian"/>
|
||||
<locale code="lt_LT" name="Lithuania"/>
|
||||
<locale code="mn_MN" name="Mongolian"/>
|
||||
<locale code="ne_NE" name="Nepali"/>
|
||||
<locale code="no_NO" name="Norwegian"/>
|
||||
<locale code="oc" name="Occitan"/>
|
||||
<locale code="pl_PL" name="Polish"/>
|
||||
<locale code="pt_BR" name="Portuguese (Brazilian)"/>
|
||||
<locale code="pt_PT" name="Portuguese"/>
|
||||
<locale code="ro_RO" name="Romanian"/>
|
||||
<locale code="ru_RU" name="Russian"/>
|
||||
<locale code="sr_SR" name="Serbian (Cyrillic)"/>
|
||||
<locale code="sr_RS" name="Serbian (Latin)"/>
|
||||
<locale code="si_LK" name="Sinhala"/>
|
||||
<locale code="sk_SK" name="Slovak"/>
|
||||
<locale code="sl_SL" name="Slovenian"/>
|
||||
<locale code="es_ES" name="Spanish"/>
|
||||
<locale code="es_LA" name="Spanish (Latin American)"/>
|
||||
<locale code="sv_SE" name="Swedish"/>
|
||||
<locale code="th_TH" name="Thai"/>
|
||||
<locale code="tr_TR" name="Turkish"/>
|
||||
<locale code="uk_UA" name="Ukrainian"/>
|
||||
<locale code="vi_VN" name="Vietnamese"/>
|
||||
<locale code="cy_GB" name="Welsh"/>
|
||||
</locales>
|
78
clients/flash/web-client/src/main/resources/profiles.xml
Executable file
78
clients/flash/web-client/src/main/resources/profiles.xml
Executable file
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0"?>
|
||||
<profiles fallbackLocale="en_US">
|
||||
<profile id="low">
|
||||
<locale>
|
||||
<en_US>Low quality</en_US>
|
||||
<pt_BR>Baixa qualidade</pt_BR>
|
||||
</locale>
|
||||
<width>160</width>
|
||||
<height>120</height>
|
||||
<keyFrameInterval>5</keyFrameInterval>
|
||||
<modeFps>10</modeFps>
|
||||
<qualityBandwidth>0</qualityBandwidth>
|
||||
<qualityPicture>90</qualityPicture>
|
||||
<enableH264>true</enableH264>
|
||||
<h264Level>2.1</h264Level>
|
||||
<h264Profile>main</h264Profile>
|
||||
</profile>
|
||||
<profile id="medium" default="true">
|
||||
<locale>
|
||||
<en_US>Medium quality</en_US>
|
||||
<pt_BR>Média qualidade</pt_BR>
|
||||
</locale>
|
||||
<width>320</width>
|
||||
<height>240</height>
|
||||
<keyFrameInterval>5</keyFrameInterval>
|
||||
<modeFps>10</modeFps>
|
||||
<qualityBandwidth>0</qualityBandwidth>
|
||||
<qualityPicture>90</qualityPicture>
|
||||
<enableH264>true</enableH264>
|
||||
<h264Level>2.1</h264Level>
|
||||
<h264Profile>main</h264Profile>
|
||||
</profile>
|
||||
<profile id="high">
|
||||
<locale>
|
||||
<en_US>High quality</en_US>
|
||||
<pt_BR>Alta qualidade</pt_BR>
|
||||
</locale>
|
||||
<width>640</width>
|
||||
<height>480</height>
|
||||
<keyFrameInterval>5</keyFrameInterval>
|
||||
<modeFps>15</modeFps>
|
||||
<qualityBandwidth>0</qualityBandwidth>
|
||||
<qualityPicture>90</qualityPicture>
|
||||
<enableH264>true</enableH264>
|
||||
<h264Level>2.1</h264Level>
|
||||
<h264Profile>main</h264Profile>
|
||||
</profile>
|
||||
<profile id="wide">
|
||||
<locale>
|
||||
<en_US>Widescreen</en_US>
|
||||
<pt_BR>Panorâmico</pt_BR>
|
||||
</locale>
|
||||
<width>1280</width>
|
||||
<height>720</height>
|
||||
<keyFrameInterval>5</keyFrameInterval>
|
||||
<modeFps>15</modeFps>
|
||||
<qualityBandwidth>0</qualityBandwidth>
|
||||
<qualityPicture>90</qualityPicture>
|
||||
<enableH264>true</enableH264>
|
||||
<h264Level>2.1</h264Level>
|
||||
<h264Profile>main</h264Profile>
|
||||
</profile>
|
||||
<profile id="lowlatency">
|
||||
<locale>
|
||||
<en_US>Low Latency</en_US>
|
||||
<pt_BR>Baixa Latência</pt_BR>
|
||||
</locale>
|
||||
<width>640</width>
|
||||
<height>480</height>
|
||||
<keyFrameInterval>5</keyFrameInterval>
|
||||
<modeFps>15</modeFps>
|
||||
<qualityBandwidth>0</qualityBandwidth>
|
||||
<qualityPicture>90</qualityPicture>
|
||||
<enableH264>false</enableH264>
|
||||
<h264Level>2.1</h264Level>
|
||||
<h264Profile>main</h264Profile>
|
||||
</profile>
|
||||
</profiles>
|
4
clients/flash/web-client/src/main/resources/swfobject/swfobject.js
Executable file
4
clients/flash/web-client/src/main/resources/swfobject/swfobject.js
Executable file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user