You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
895 lines
27 KiB
895 lines
27 KiB
/* globals SIP,user,moment, Stopwatch */
|
|
|
|
var ctxSip;
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
|
if (typeof(user) === 'undefined') {
|
|
|
|
|
|
user = JSON.parse(localStorage.getItem('SIPCreds'));
|
|
}
|
|
ctxSip = {
|
|
|
|
config : {
|
|
media : {
|
|
remote : {
|
|
video: document.getElementById('audioRemote'),
|
|
audio: document.getElementById('audioRemote')
|
|
}
|
|
},
|
|
peerConnectionOptions : {
|
|
rtcConfiguration : {
|
|
iceServers : [{urls:"stun:stun.l.google.com:19302"}]
|
|
}
|
|
},
|
|
password : user.Pass,
|
|
authorizationUser: user.User,
|
|
displayName : user.Display,
|
|
uri : user.User +'@'+user.Realm,
|
|
transportOptions: {
|
|
traceSip: true,
|
|
wsServers: user.WSServer,
|
|
},
|
|
registerExpires : 30,
|
|
ua: {}
|
|
},
|
|
ringtone : document.getElementById('ringtone'),
|
|
ringbacktone : document.getElementById('ringbacktone'),
|
|
dtmfTone : document.getElementById('dtmfTone'),
|
|
|
|
Sessions : [],
|
|
callTimers : {},
|
|
callActiveID : null,
|
|
callVolume : 1,
|
|
Stream : null,
|
|
|
|
/**
|
|
* Parses a SIP uri and returns a formatted US phone number.
|
|
*
|
|
* @param {string} phone number or uri to format
|
|
* @return {string} formatted number
|
|
*/
|
|
formatPhone : function(phone) {
|
|
|
|
var num;
|
|
|
|
if (phone.indexOf('@')) {
|
|
num = phone.split('@')[0];
|
|
} else {
|
|
num = phone;
|
|
}
|
|
|
|
num = num.toString().replace(/[^0-9]/g, '');
|
|
|
|
if (num.length === 10) {
|
|
return '(' + num.substr(0, 3) + ') ' + num.substr(3, 3) + '-' + num.substr(6,4);
|
|
} else if (num.length === 11) {
|
|
return '0' + num.substr(2);
|
|
} else {
|
|
return num;
|
|
}
|
|
},
|
|
|
|
// Sound methods
|
|
startRingTone : function() {
|
|
try { ctxSip.ringtone.play(); } catch (e) { }
|
|
},
|
|
|
|
stopRingTone : function() {
|
|
try { ctxSip.ringtone.pause(); } catch (e) { }
|
|
},
|
|
|
|
startRingbackTone : function() {
|
|
try { ctxSip.ringbacktone.play(); } catch (e) { }
|
|
},
|
|
|
|
stopRingbackTone : function() {
|
|
try { ctxSip.ringbacktone.pause(); } catch (e) { }
|
|
},
|
|
|
|
// Genereates a rendom string to ID a call
|
|
getUniqueID : function() {
|
|
return Math.random().toString(36).substr(2, 9);
|
|
},
|
|
|
|
newSession : function(newSess) {
|
|
|
|
newSess.displayName = newSess.remoteIdentity.displayName || newSess.remoteIdentity.uri.user;
|
|
newSess.ctxid = ctxSip.getUniqueID();
|
|
|
|
var status;
|
|
|
|
if (newSess.direction === 'incoming') {
|
|
status = "Incoming: "+ newSess.displayName;
|
|
ctxSip.startRingTone();
|
|
|
|
} else {
|
|
status = "Trying: "+ newSess.displayName;
|
|
ctxSip.startRingbackTone();
|
|
}
|
|
|
|
ctxSip.logCall(newSess, 'ringing');
|
|
|
|
ctxSip.setCallSessionStatus(status);
|
|
|
|
// EVENT CALLBACKS
|
|
|
|
|
|
var remoteVideo = document.getElementById('audioRemote');
|
|
var localVideo = document.getElementById('audioRemote');
|
|
|
|
|
|
|
|
newSess.on('trackAdded', function() {
|
|
// We need to check the peer connection to determine which track was added
|
|
|
|
var pc = newSess.sessionDescriptionHandler.peerConnection;
|
|
|
|
// Gets remote tracks
|
|
var remoteStream = new MediaStream();
|
|
pc.getReceivers().forEach(function(receiver) {
|
|
remoteStream.addTrack(receiver.track);
|
|
});
|
|
remoteVideo.srcObject = remoteStream;
|
|
remoteVideo.play();
|
|
|
|
});
|
|
|
|
newSess.on('progress',function(e) {
|
|
if (e.direction === 'outgoing') {
|
|
ctxSip.setCallSessionStatus('Calling...');
|
|
}
|
|
});
|
|
|
|
newSess.on('connecting',function(e) {
|
|
if (e.direction === 'outgoing') {
|
|
ctxSip.setCallSessionStatus('Connecting...');
|
|
}
|
|
});
|
|
|
|
newSess.on('accepted',function(e) {
|
|
// If there is another active call, hold it
|
|
if (ctxSip.callActiveID && ctxSip.callActiveID !== newSess.ctxid) {
|
|
ctxSip.phoneHoldButtonPressed(ctxSip.callActiveID);
|
|
}
|
|
|
|
|
|
ctxSip.stopRingbackTone();
|
|
ctxSip.stopRingTone();
|
|
ctxSip.setCallSessionStatus('Answered');
|
|
ctxSip.logCall(newSess, 'answered');
|
|
ctxSip.callActiveID = newSess.ctxid;
|
|
|
|
});
|
|
|
|
newSess.on('hold', function(e) {
|
|
ctxSip.callActiveID = null;
|
|
ctxSip.logCall(newSess, 'holding');
|
|
ctxSip.setCallSessionStatus("Holding");
|
|
});
|
|
|
|
newSess.on('unhold', function(e) {
|
|
ctxSip.logCall(newSess, 'resumed');
|
|
ctxSip.callActiveID = newSess.ctxid;
|
|
ctxSip.setCallSessionStatus("Answered");
|
|
});
|
|
|
|
newSess.on('muted', function(e) {
|
|
ctxSip.Sessions[newSess.ctxid].isMuted = true;
|
|
ctxSip.setCallSessionStatus("Muted");
|
|
});
|
|
|
|
newSess.on('unmuted', function(e) {
|
|
ctxSip.Sessions[newSess.ctxid].isMuted = false;
|
|
ctxSip.setCallSessionStatus("Answered");
|
|
});
|
|
|
|
newSess.on('cancel', function(e) {
|
|
ctxSip.stopRingTone();
|
|
ctxSip.stopRingbackTone();
|
|
ctxSip.setCallSessionStatus("Canceled");
|
|
if (this.direction === 'outgoing') {
|
|
ctxSip.callActiveID = null;
|
|
newSess = null;
|
|
ctxSip.logCall(this, 'ended');
|
|
}
|
|
});
|
|
|
|
newSess.on('bye', function(e) {
|
|
ctxSip.stopRingTone();
|
|
ctxSip.stopRingbackTone();
|
|
ctxSip.setCallSessionStatus("");
|
|
ctxSip.logCall(newSess, 'ended');
|
|
ctxSip.callActiveID = null;
|
|
newSess = null;
|
|
});
|
|
|
|
newSess.on('failed',function(e) {
|
|
ctxSip.stopRingTone();
|
|
ctxSip.stopRingbackTone();
|
|
ctxSip.setCallSessionStatus('Terminated');
|
|
});
|
|
|
|
newSess.on('rejected',function(e) {
|
|
ctxSip.stopRingTone();
|
|
ctxSip.stopRingbackTone();
|
|
ctxSip.setCallSessionStatus('Rejected');
|
|
ctxSip.callActiveID = null;
|
|
ctxSip.logCall(this, 'ended');
|
|
newSess = null;
|
|
});
|
|
|
|
|
|
|
|
ctxSip.Sessions[newSess.ctxid] = newSess;
|
|
|
|
|
|
},
|
|
|
|
// getUser media request refused or device was not present
|
|
getUserMediaFailure : function(e) {
|
|
window.console.error('getUserMedia failed:', e);
|
|
ctxSip.setError(true, 'Media Error.', 'You must allow access to your microphone. Check the address bar.', true);
|
|
},
|
|
|
|
getUserMediaSuccess : function(stream) {
|
|
ctxSip.Stream = stream;
|
|
},
|
|
|
|
/**
|
|
* sets the ui call status field
|
|
*
|
|
* @param {string} status
|
|
*/
|
|
setCallSessionStatus : function(status) {
|
|
$('#txtCallStatus').html(status);
|
|
},
|
|
|
|
/**
|
|
* sets the ui connection status field
|
|
*
|
|
* @param {string} status
|
|
*/
|
|
setStatus : function(status) {
|
|
$("#txtRegStatus").html('<i class="fa fa-signal"></i> '+status);
|
|
},
|
|
|
|
/**
|
|
* logs a call to localstorage
|
|
*
|
|
* @param {object} session
|
|
* @param {string} status Enum 'ringing', 'answered', 'ended', 'holding', 'resumed'
|
|
*/
|
|
logCall : function(session, status) {
|
|
|
|
var log = {
|
|
clid : session.displayName,
|
|
uri : session.remoteIdentity.uri.toString(),
|
|
id : session.ctxid,
|
|
time : new Date().getTime()
|
|
},
|
|
calllog = JSON.parse(localStorage.getItem('sipCalls'));
|
|
|
|
if (!calllog) { calllog = {}; }
|
|
|
|
if (!calllog.hasOwnProperty(session.ctxid)) {
|
|
calllog[log.id] = {
|
|
id : log.id,
|
|
clid : log.clid,
|
|
uri : log.uri,
|
|
start : log.time,
|
|
flow : session.direction
|
|
};
|
|
}
|
|
|
|
if (status === 'ended') {
|
|
calllog[log.id].stop = log.time;
|
|
}
|
|
|
|
if (status === 'ended' && calllog[log.id].status === 'ringing') {
|
|
calllog[log.id].status = 'missed';
|
|
} else {
|
|
calllog[log.id].status = status;
|
|
}
|
|
|
|
localStorage.setItem('sipCalls', JSON.stringify(calllog));
|
|
ctxSip.logShow();
|
|
},
|
|
|
|
/**
|
|
* adds a ui item to the call log
|
|
*
|
|
* @param {object} item log item
|
|
*/
|
|
logItem : function(item) {
|
|
|
|
var callActive = (item.status !== 'ended' && item.status !== 'missed'),
|
|
callLength = (item.status !== 'ended')? '<span id="'+item.id+'"></span>': moment.duration(item.stop - item.start).humanize(),
|
|
callClass = '',
|
|
callIcon,
|
|
i;
|
|
|
|
switch (item.status) {
|
|
case 'ringing' :
|
|
callClass = 'list-group-item-success';
|
|
callIcon = 'fa-bell';
|
|
break;
|
|
|
|
case 'missed' :
|
|
callClass = 'list-group-item-danger';
|
|
if (item.flow === "incoming") { callIcon = 'fa-chevron-left'; }
|
|
if (item.flow === "outgoing") { callIcon = 'fa-chevron-right'; }
|
|
break;
|
|
|
|
case 'holding' :
|
|
callClass = 'list-group-item-warning';
|
|
callIcon = 'fa-pause';
|
|
break;
|
|
|
|
case 'answered' :
|
|
case 'resumed' :
|
|
callClass = 'list-group-item-info';
|
|
callIcon = 'fa-phone-square';
|
|
break;
|
|
|
|
case 'ended' :
|
|
if (item.flow === "incoming") { callIcon = 'fa-chevron-left'; }
|
|
if (item.flow === "outgoing") { callIcon = 'fa-chevron-right'; }
|
|
break;
|
|
}
|
|
|
|
|
|
i = '<div class="list-group-item sip-logitem clearfix '+callClass+'" data-uri="'+item.uri+'" data-sessionid="'+item.id+'" title="Double Click to Call">';
|
|
i += '<div class="clearfix"><div class="pull-left">';
|
|
i += '<i class="fa fa-fw '+callIcon+' fa-fw"></i> <strong>'+ctxSip.formatPhone(item.uri)+'</strong><br><small>'+moment(item.start).format('MM/DD hh:mm:ss a')+'</small>';
|
|
i += '</div>';
|
|
i += '<div class="pull-left text-left"><em>'+item.clid+'</em><br>' + callLength+'</div></div>';
|
|
|
|
if (callActive) {
|
|
i += '<div class="btn-group btn-group-xs pull-right">';
|
|
if (item.status === 'ringing' && item.flow === 'incoming') {
|
|
i += '<button class="btn btn-xs btn-success btnCall" title="Call"><i class="fa fa-phone"></i></button>';
|
|
} else {
|
|
i += '<button class="btn btn-xs btn-primary btnHoldResume" title="Hold"><i class="fa fa-pause"></i></button>';
|
|
i += '<button class="btn btn-xs btn-info btnTransfer" title="Transfer"><i class="fa fa-random"></i></button>';
|
|
i += '<button class="btn btn-xs btn-warning btnMute" title="Mute"><i class="fa fa-fw fa-microphone"></i></button>';
|
|
}
|
|
i += '<button class="btn btn-xs btn-danger btnHangUp" title="Hangup"><i class="fa fa-stop"></i></button>';
|
|
i += '</div>';
|
|
}
|
|
i += '</div>';
|
|
|
|
$('#sip-logitems').append(i);
|
|
|
|
|
|
// Start call timer on answer
|
|
if (item.status === 'answered') {
|
|
var tEle = document.getElementById(item.id);
|
|
ctxSip.callTimers[item.id] = new Stopwatch(tEle);
|
|
ctxSip.callTimers[item.id].start();
|
|
}
|
|
|
|
if (callActive && item.status !== 'ringing') {
|
|
ctxSip.callTimers[item.id].start({startTime : item.start});
|
|
}
|
|
|
|
$('#sip-logitems').scrollTop(0);
|
|
},
|
|
|
|
/**
|
|
* updates the call log ui
|
|
*/
|
|
logShow : function() {
|
|
|
|
var calllog = JSON.parse(localStorage.getItem('sipCalls')),
|
|
x = [];
|
|
|
|
if (calllog !== null) {
|
|
|
|
$('#sip-splash').addClass('hide');
|
|
$('#sip-log').removeClass('hide');
|
|
|
|
// empty existing logs
|
|
$('#sip-logitems').empty();
|
|
|
|
// JS doesn't guarantee property order so
|
|
// create an array with the start time as
|
|
// the key and sort by that.
|
|
|
|
// Add start time to array
|
|
$.each(calllog, function(k,v) {
|
|
x.push(v);
|
|
});
|
|
|
|
// sort descending
|
|
x.sort(function(a, b) {
|
|
return b.start - a.start;
|
|
});
|
|
|
|
$.each(x, function(k, v) {
|
|
ctxSip.logItem(v);
|
|
});
|
|
|
|
} else {
|
|
$('#sip-splash').removeClass('hide');
|
|
$('#sip-log').addClass('hide');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* removes log items from localstorage and updates the UI
|
|
*/
|
|
logClear : function() {
|
|
|
|
localStorage.removeItem('sipCalls');
|
|
ctxSip.logShow();
|
|
},
|
|
|
|
sipCall : function(target) {
|
|
|
|
try {
|
|
var s = ctxSip.phone.invite(target, {
|
|
media : {
|
|
remote : {
|
|
video: document.getElementById('audioRemote'),
|
|
audio: document.getElementById('audioRemote')
|
|
}
|
|
},
|
|
sessionDescriptionHandlerOptions : {
|
|
constraints : { audio : true, video : false },
|
|
rtcConfiguration : { RTCConstraints : { "optional": [{ 'DtlsSrtpKeyAgreement': 'true'} ]}, stream : ctxSip.Stream }
|
|
|
|
}
|
|
});
|
|
s.direction = 'outgoing';
|
|
ctxSip.newSession(s);
|
|
|
|
var remoteVideo = document.getElementById('audioRemote');
|
|
var localVideo = document.getElementById('audioRemote');
|
|
|
|
|
|
|
|
s.on('trackAdded', function() {
|
|
// We need to check the peer connection to determine which track was added
|
|
|
|
var pc = s.sessionDescriptionHandler.peerConnection;
|
|
|
|
// Gets remote tracks
|
|
var remoteStream = new MediaStream();
|
|
pc.getReceivers().forEach(function(receiver) {
|
|
remoteStream.addTrack(receiver.track);
|
|
});
|
|
remoteVideo.srcObject = remoteStream;
|
|
remoteVideo.play();
|
|
});
|
|
|
|
|
|
} catch(e) {
|
|
throw(e);
|
|
}
|
|
},
|
|
|
|
sipTransfer : function(sessionid) {
|
|
|
|
var s = ctxSip.Sessions[sessionid],
|
|
target = window.prompt('Enter destination number', '');
|
|
|
|
ctxSip.setCallSessionStatus('<i>Transfering the call...</i>');
|
|
s.refer(target);
|
|
},
|
|
|
|
sipHangUp : function(sessionid) {
|
|
|
|
var s = ctxSip.Sessions[sessionid];
|
|
// s.terminate();
|
|
if (!s) {
|
|
return;
|
|
} else if (s.startTime) {
|
|
s.bye();
|
|
} else if (s.reject) {
|
|
s.reject();
|
|
} else if (s.cancel) {
|
|
s.cancel();
|
|
}
|
|
|
|
},
|
|
|
|
sipSendDTMF : function(digit) {
|
|
|
|
try { ctxSip.dtmfTone.play(); } catch(e) { }
|
|
|
|
var a = ctxSip.callActiveID;
|
|
if (a) {
|
|
var s = ctxSip.Sessions[a];
|
|
s.dtmf(digit);
|
|
}
|
|
},
|
|
|
|
phoneCallButtonPressed : function(sessionid) {
|
|
|
|
var s = ctxSip.Sessions[sessionid],
|
|
target = $("#numDisplay").val();
|
|
|
|
if (!s) {
|
|
|
|
$("#numDisplay").val("");
|
|
ctxSip.sipCall(target);
|
|
|
|
} else if (s.accept && !s.startTime) {
|
|
|
|
s.accept({
|
|
media : {
|
|
remote : {
|
|
video: document.getElementById('audioRemote'),
|
|
audio: document.getElementById('audioRemote')
|
|
}
|
|
},
|
|
sessionDescriptionHandlerOptions : {
|
|
constraints : { audio : true, video : false },
|
|
rtcConfiguration : { RTCConstraints : { "optional": [{ 'DtlsSrtpKeyAgreement': 'true'} ]}, stream : ctxSip.Stream }
|
|
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
phoneMuteButtonPressed : function (sessionid) {
|
|
|
|
var s = ctxSip.Sessions[sessionid];
|
|
|
|
if (!s.isMuted) {
|
|
s.mute();
|
|
} else {
|
|
s.unmute();
|
|
}
|
|
},
|
|
|
|
phoneHoldButtonPressed : function(sessionid) {
|
|
|
|
var s = ctxSip.Sessions[sessionid];
|
|
var direction = s.sessionDescriptionHandler.getDirection();
|
|
|
|
if (direction === 'sendrecv') {
|
|
console.log('Call is not on hold');
|
|
s.hold();
|
|
} else {
|
|
console.log('Call is on hold');
|
|
s.unhold();
|
|
}
|
|
},
|
|
|
|
|
|
setError : function(err, title, msg, closable) {
|
|
|
|
// Show modal if err = true
|
|
if (err === true) {
|
|
$("#mdlError p").html(msg);
|
|
$("#mdlError").modal('show');
|
|
|
|
if (closable) {
|
|
var b = '<button type="button" class="close" data-dismiss="modal">×</button>';
|
|
$("#mdlError .modal-header").find('button').remove();
|
|
$("#mdlError .modal-header").prepend(b);
|
|
$("#mdlError .modal-title").html(title);
|
|
$("#mdlError").modal({ keyboard : true });
|
|
} else {
|
|
$("#mdlError .modal-header").find('button').remove();
|
|
$("#mdlError .modal-title").html(title);
|
|
$("#mdlError").modal({ keyboard : false });
|
|
}
|
|
// $('#numDisplay').prop('disabled', 'disabled');
|
|
} else {
|
|
$('#numDisplay').removeProp('disabled');
|
|
$("#mdlError").modal('hide');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Tests for a capable browser, return bool, and shows an
|
|
* error modal on fail.
|
|
*/
|
|
hasWebRTC : function() {
|
|
|
|
if (navigator.webkitGetUserMedia) {
|
|
return true;
|
|
} else if (navigator.mozGetUserMedia) {
|
|
return true;
|
|
} else if (navigator.getUserMedia) {
|
|
return true;
|
|
} else {
|
|
ctxSip.setError(true, 'Unsupported Browser.', 'Your browser does not support the features required for this phone.');
|
|
window.console.error("WebRTC support not found");
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Throw an error if the browser can't hack it.
|
|
if (!ctxSip.hasWebRTC()) {
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctxSip.phone = new SIP.UA(ctxSip.config);
|
|
|
|
|
|
ctxSip.phone.on('connected', function(e) {
|
|
ctxSip.setStatus("Connected");
|
|
ctxSip.setError(false)
|
|
});
|
|
|
|
ctxSip.phone.on('disconnected', function(e) {
|
|
ctxSip.setStatus("Disconnected");
|
|
|
|
// disable phone
|
|
ctxSip.setError(true, 'Websocket Disconnected.', 'An Error occurred connecting to the websocket.');
|
|
|
|
});
|
|
|
|
ctxSip.phone.on('registered', function(e) {
|
|
ctxSip.setError(false)
|
|
var closeEditorWarning = function() {
|
|
return 'If you close this window, you will not be able to make or receive calls from your browser.';
|
|
};
|
|
|
|
var closePhone = function() {
|
|
// stop the phone on unload
|
|
localStorage.removeItem('ctxPhone');
|
|
ctxSip.phone.stop();
|
|
};
|
|
|
|
window.onbeforeunload = closeEditorWarning;
|
|
window.onunload = closePhone;
|
|
|
|
// This key is set to prevent multiple windows.
|
|
localStorage.setItem('ctxPhone', 'true');
|
|
|
|
$("#mldError").modal('hide');
|
|
ctxSip.setStatus("Ready");
|
|
|
|
|
|
// Get the userMedia and cache the stream
|
|
// if (SIP.WebRTC.isSupported()) {
|
|
// SIP.WebRTC.getUserMedia({ audio : true, video : false }, ctxSip.getUserMediaSuccess, ctxSip.getUserMediaFailure);
|
|
// }
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ctxSip.phone.on('registrationFailed', function(e) {
|
|
console.log(e)
|
|
ctxSip.setError(true, 'Registration Error.', 'An Error occurred registering your phone. Check your settings.');
|
|
ctxSip.setStatus("Error: Registration Failed");
|
|
});
|
|
|
|
ctxSip.phone.on('unregistered', function(e) {
|
|
ctxSip.setError(true, 'Registration Error.', 'An Error occurred registering your phone. Please wait while we try to connect it again.');
|
|
ctxSip.setStatus("Error: Registration Failed");
|
|
});
|
|
|
|
ctxSip.phone.on('invite',
|
|
|
|
function (incomingSession) {
|
|
|
|
var s = incomingSession;
|
|
|
|
s.direction = 'incoming';
|
|
ctxSip.newSession(s);
|
|
|
|
|
|
},);
|
|
|
|
// Auto-focus number input on backspace.
|
|
$('#sipClient').keydown(function(event) {
|
|
if (event.which === 8) {
|
|
$('#numDisplay').focus();
|
|
}
|
|
});
|
|
|
|
$('#numDisplay').keypress(function(e) {
|
|
// Enter pressed? so Dial.
|
|
if (e.which === 13) {
|
|
ctxSip.phoneCallButtonPressed();
|
|
}
|
|
});
|
|
|
|
|
|
$('#phoneIcon').click(function(eveny) {
|
|
// Enter pressed? so Dial.
|
|
event.preventDefault();
|
|
ctxSip.phoneCallButtonPressed();
|
|
});
|
|
|
|
|
|
$('.digit').click(function(event) {
|
|
event.preventDefault();
|
|
var num = $('#numDisplay').val(),
|
|
dig = $(this).data('digit');
|
|
|
|
$('#numDisplay').val(num+dig);
|
|
|
|
ctxSip.sipSendDTMF(dig);
|
|
return false;
|
|
});
|
|
|
|
$('#phoneUI .dropdown-menu').click(function(e) {
|
|
e.preventDefault();
|
|
});
|
|
|
|
$('#phoneUI').delegate('.btnCall', 'click', function(event) {
|
|
ctxSip.phoneCallButtonPressed();
|
|
// to close the dropdown
|
|
return true;
|
|
});
|
|
|
|
$('.sipLogClear').click(function(event) {
|
|
event.preventDefault();
|
|
ctxSip.logClear();
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem .btnCall', 'click', function(event) {
|
|
var sessionid = $(this).closest('.sip-logitem').data('sessionid');
|
|
ctxSip.phoneCallButtonPressed(sessionid);
|
|
return false;
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem .btnHoldResume', 'click', function(event) {
|
|
var sessionid = $(this).closest('.sip-logitem').data('sessionid');
|
|
ctxSip.phoneHoldButtonPressed(sessionid);
|
|
return false;
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem .btnHangUp', 'click', function(event) {
|
|
var sessionid = $(this).closest('.sip-logitem').data('sessionid');
|
|
ctxSip.sipHangUp(sessionid);
|
|
return false;
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem .btnTransfer', 'click', function(event) {
|
|
var sessionid = $(this).closest('.sip-logitem').data('sessionid');
|
|
ctxSip.sipTransfer(sessionid);
|
|
return false;
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem .btnMute', 'click', function(event) {
|
|
var sessionid = $(this).closest('.sip-logitem').data('sessionid');
|
|
ctxSip.phoneMuteButtonPressed(sessionid);
|
|
return false;
|
|
});
|
|
|
|
$('#sip-logitems').delegate('.sip-logitem', 'dblclick', function(event) {
|
|
event.preventDefault();
|
|
|
|
var uri = $(this).data('uri');
|
|
$('#numDisplay').val(uri);
|
|
ctxSip.phoneCallButtonPressed();
|
|
});
|
|
|
|
$('#sldVolume').on('change', function() {
|
|
|
|
var v = $(this).val() / 100,
|
|
// player = $('audio').get()[0],
|
|
btn = $('#btnVol'),
|
|
icon = $('#btnVol').find('i'),
|
|
active = ctxSip.callActiveID;
|
|
|
|
// Set the object and media stream volumes
|
|
if (ctxSip.Sessions[active]) {
|
|
ctxSip.Sessions[active].player.volume = v;
|
|
ctxSip.callVolume = v;
|
|
}
|
|
|
|
// Set the others
|
|
$('audio').each(function() {
|
|
$(this).get()[0].volume = v;
|
|
});
|
|
|
|
if (v < 0.1) {
|
|
btn.removeClass(function (index, css) {
|
|
return (css.match (/(^|\s)btn\S+/g) || []).join(' ');
|
|
})
|
|
.addClass('btn btn-sm btn-danger');
|
|
icon.removeClass().addClass('fa fa-fw fa-volume-off');
|
|
} else if (v < 0.8) {
|
|
btn.removeClass(function (index, css) {
|
|
return (css.match (/(^|\s)btn\S+/g) || []).join(' ');
|
|
}).addClass('btn btn-sm btn-info');
|
|
icon.removeClass().addClass('fa fa-fw fa-volume-down');
|
|
} else {
|
|
btn.removeClass(function (index, css) {
|
|
return (css.match (/(^|\s)btn\S+/g) || []).join(' ');
|
|
}).addClass('btn btn-sm btn-primary');
|
|
icon.removeClass().addClass('fa fa-fw fa-volume-up');
|
|
}
|
|
return false;
|
|
});
|
|
|
|
// Hide the spalsh after 3 secs.
|
|
setTimeout(function() {
|
|
ctxSip.logShow();
|
|
}, 3000);
|
|
|
|
|
|
/**
|
|
* Stopwatch object used for call timers
|
|
*
|
|
* @param {dom element} elem
|
|
* @param {[object]} options
|
|
*/
|
|
var Stopwatch = function(elem, options) {
|
|
|
|
// private functions
|
|
function createTimer() {
|
|
return document.createElement("span");
|
|
}
|
|
|
|
var timer = createTimer(),
|
|
offset,
|
|
clock,
|
|
interval;
|
|
|
|
// default options
|
|
options = options || {};
|
|
options.delay = options.delay || 1000;
|
|
options.startTime = options.startTime || Date.now();
|
|
|
|
// append elements
|
|
elem.appendChild(timer);
|
|
|
|
function start() {
|
|
if (!interval) {
|
|
offset = options.startTime;
|
|
interval = setInterval(update, options.delay);
|
|
}
|
|
}
|
|
|
|
function stop() {
|
|
if (interval) {
|
|
clearInterval(interval);
|
|
interval = null;
|
|
}
|
|
}
|
|
|
|
function reset() {
|
|
clock = 0;
|
|
render();
|
|
}
|
|
|
|
function update() {
|
|
clock += delta();
|
|
render();
|
|
}
|
|
|
|
function render() {
|
|
timer.innerHTML = moment(clock).format('mm:ss');
|
|
}
|
|
|
|
function delta() {
|
|
var now = Date.now(),
|
|
d = now - offset;
|
|
|
|
offset = now;
|
|
return d;
|
|
}
|
|
|
|
// initialize
|
|
reset();
|
|
|
|
// public API
|
|
this.start = start; //function() { start; }
|
|
this.stop = stop; //function() { stop; }
|
|
};
|
|
|
|
});
|