phone.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. function sanitize_string(str) {
  2. let temp = document.createElement('div');
  3. temp.textContent = str;
  4. return temp.innerHTML;
  5. }
  6. let user_agent;
  7. let session;
  8. let answer_time;
  9. let session_hungup = false;
  10. var config = {
  11. uri: '<?php echo $user_extension.'@'.$domain_name; ?>',
  12. ws_servers: 'wss://<?php echo $domain_name; ?>:7443',
  13. authorizationUser: '<?php echo $user_extension; ?>',
  14. password: atob('<?php echo base64_encode($user_password); ?>'),
  15. registerExpires: 120,
  16. displayName: "<?php echo $user_extension; ?>"
  17. };
  18. user_agent = new SIP.UA(config);
  19. //here you determine whether the call has video and audio
  20. var options = {
  21. media: {
  22. constraints: {
  23. audio: true,
  24. video: false
  25. },
  26. render: {
  27. remote: document.getElementById('remote_video'),
  28. local: document.getElementById('local_video')
  29. },
  30. RTCConstraints: {
  31. "optional": [{ 'DtlsSrtpKeyAgreement': 'true'} ]
  32. }
  33. }
  34. };
  35. //answer
  36. user_agent.on('invite', function (s) {
  37. if (typeof session !== "undefined" && session.display_name != s.remoteIdentity.displayName) {
  38. return;
  39. }
  40. //save the session to the global session
  41. session = s;
  42. session.display_name = session.remoteIdentity.displayName;
  43. session.uri_user = session.remoteIdentity.uri.user;
  44. //send the object to the browser console
  45. //console.log(session);
  46. //play the ringtone
  47. document.getElementById('ringtone').play();
  48. <?php
  49. //open the window to search for the caller id
  50. if (!empty($search_enabled) && $search_enabled == 'true') {
  51. echo " //open a window when the call is answer\n";
  52. echo " dashboard_url = 'https://".$search_domain."/".$search_path."?".$search_parameter."=' + sanitize_string(session.uri_user);\n";
  53. echo " dashboard_target = '".$search_target."';\n";
  54. if (!empty($search_width) && !empty($search_height)) {
  55. echo " window_parameters = 'width=".$search_width.",height=".$search_height."';\n";
  56. }
  57. else {
  58. echo " window_parameters = '';\n";
  59. }
  60. echo " window.open(dashboard_url, dashboard_target, window_parameters);\n";
  61. }
  62. ?>
  63. //add the caller ID
  64. document.getElementById('ringing_caller_id').innerHTML = "<div>" + sanitize_string(session.display_name) + "</div><div style='flex-basis: 100%; height: 0;'></div><div><a href='https://<?php echo $_SESSION['domain_name']; ?>/app/contacts/contacts.php?search=" + sanitize_string(session.uri_user) + "' target='_blank'>" + sanitize_string(session.uri_user) + "</a></div>";
  65. document.getElementById('active_caller_id').innerHTML = "<div>" + sanitize_string(session.display_name) + "</div><div style='flex-basis: 100%; height: 0;'></div><div><a href='https://<?php echo $_SESSION['domain_name']; ?>/app/contacts/contacts.php?search=" + sanitize_string(session.uri_user) + "' target='_blank'>" + sanitize_string(session.uri_user) + "</a></div>";
  66. //show or hide the panels
  67. document.getElementById('dialpad').style.display = "none";
  68. document.getElementById('ringing').style.display = "inline";
  69. //show or hide the buttons
  70. document.getElementById('answer').style.display = "inline";
  71. document.getElementById('decline').style.display = "inline";
  72. document.getElementById('hangup').style.display = "none";
  73. document.getElementById('mute_audio').style.display = "inline";
  74. document.getElementById('mute_video').style.display = "none";
  75. session.on('cancel', function (s) {
  76. //play the ringtone
  77. document.getElementById('ringtone').pause();
  78. //show or hide the panels
  79. document.getElementById('dialpad').style.display = "grid";
  80. document.getElementById('ringing').style.display = "none";
  81. document.getElementById('active').style.display = "none";
  82. //show or hide the buttons
  83. document.getElementById('answer').style.display = "none";
  84. document.getElementById('decline').style.display = "none";
  85. document.getElementById('hangup').style.display = "none";
  86. //clear the caller id
  87. document.getElementById('ringing_caller_id').innerHTML = '';
  88. document.getElementById('active_caller_id').innerHTML = '';
  89. //clear the answer time
  90. answer_time = null;
  91. //end the call
  92. hangup();
  93. });
  94. session.on('bye', function (s) {
  95. //play the ringtone
  96. document.getElementById('ringtone').pause();
  97. //show or hide the panels
  98. document.getElementById('dialpad').style.display = "grid";
  99. document.getElementById('ringing').style.display = "none";
  100. document.getElementById('active').style.display = "none";
  101. //show or hide the buttons
  102. document.getElementById('answer').style.display = "none";
  103. document.getElementById('decline').style.display = "none";
  104. document.getElementById('hangup').style.display = "none";
  105. //clear the answer time
  106. answer_time = null;
  107. //reset the media
  108. reset_media();
  109. //end the call
  110. if (!session || !session_hungup) {
  111. hangup();
  112. }
  113. });
  114. session.on('failed', function (s) {
  115. //play the ringtone
  116. document.getElementById('ringtone').pause();
  117. //show or hide the panels
  118. document.getElementById('dialpad').style.display = "grid";
  119. document.getElementById('ringing').style.display = "none";
  120. document.getElementById('active').style.display = "none";
  121. //show or hide the buttons
  122. document.getElementById('answer').style.display = "none";
  123. document.getElementById('decline').style.display = "none";
  124. document.getElementById('hangup').style.display = "none";
  125. //clear the answer time
  126. answer_time = null;
  127. //end the call
  128. if (!session || !session_hungup) {
  129. hangup();
  130. }
  131. });
  132. session.on('rejected', function (s) {
  133. //play the ringtone
  134. document.getElementById('ringtone').pause();
  135. //show or hide the panels
  136. document.getElementById('dialpad').style.display = "grid";
  137. document.getElementById('ringing').style.display = "none";
  138. document.getElementById('active').style.display = "none";
  139. //show or hide the buttons
  140. document.getElementById('answer').style.display = "none";
  141. document.getElementById('decline').style.display = "none";
  142. document.getElementById('hangup').style.display = "none";
  143. //clear the answer time
  144. answer_time = null;
  145. //end the call
  146. hangup();
  147. });
  148. });
  149. function answer() {
  150. //set the session state
  151. session_hungup = false;
  152. //continue if the session exists
  153. if (!session) {
  154. return false;
  155. }
  156. //start the answer time
  157. answer_time = Date.now();
  158. //pause the ringtone
  159. document.getElementById('ringtone').pause();
  160. //answer the call
  161. session.accept({
  162. media: {
  163. constraints: {
  164. audio: true,
  165. video: false
  166. },
  167. render: {
  168. remote: document.getElementById('remote_video'),
  169. local: document.getElementById('local_video')
  170. },
  171. RTCConstraints: {
  172. "optional": [{ 'DtlsSrtpKeyAgreement': 'true'} ]
  173. }
  174. }
  175. });
  176. //show the or hide the panels
  177. document.getElementById('dialpad').style.display = "none";
  178. document.getElementById('ringing').style.display = "none";
  179. document.getElementById('active').style.display = "grid";
  180. document.getElementById('destination').value = '';
  181. //show or hide the buttons
  182. document.getElementById('answer').style.display = "none";
  183. document.getElementById('decline').style.display = "none";
  184. document.getElementById('unhold').style.display = "none";
  185. document.getElementById('hangup').style.display = "inline";
  186. }
  187. // Function to pad numbers with leading zeros
  188. function pad(number, length) {
  189. return (number < 10 ? '0' : '') + number;
  190. }
  191. //function to get the current time in seconds
  192. function get_session_time() {
  193. if (answer_time) {
  194. // get the elapsed time using the answer time
  195. elapsed_time = Date.now() - answer_time;
  196. // Calculate hours, minutes, and seconds
  197. var hours = Math.floor(elapsed_time / (1000 * 60 * 60));
  198. var minutes = Math.floor((elapsed_time % (1000 * 60 * 60)) / (1000 * 60));
  199. var seconds = Math.floor((elapsed_time % (1000 * 60)) / 1000);
  200. // Format the time with leading zeros if necessary
  201. var formatted_time = pad(hours, 2) + ":" + pad(minutes, 2) + ":" + pad(seconds, 2);
  202. // Update the element with id="elapsed-time" to display the formatted elapsed time
  203. document.getElementById("answer_time").textContent = formatted_time;
  204. }
  205. else {
  206. console.log('Call has not been answered yet');
  207. return null;
  208. }
  209. }
  210. //update elapsed time every second
  211. setInterval(get_session_time, 1000);
  212. //function to reset media after a call ends
  213. function reset_media() {
  214. const videoElements = [document.getElementById('remote_video'), document.getElementById('local_video')];
  215. videoElements.forEach(video => {
  216. video.srcObject = null;
  217. video.pause();
  218. });
  219. }
  220. //function used to end the session
  221. function hangup() {
  222. //return immediately if the session is already hungup
  223. if (!session || session_hungup || session.status === SIP.Session.C.STATUS_TERMINATED) {
  224. return;
  225. }
  226. //set the session state as hungup
  227. session_hungup = true;
  228. //end the session if active
  229. if (session.status === SIP.Session.C.STATUS_CONFIRMED || session.status === SIP.Session.C.STATUS_ANSWERED) {
  230. session.bye();
  231. } else {
  232. session.terminate();
  233. }
  234. //reset the media
  235. reset_media();
  236. //show or hide the panels
  237. document.getElementById('dialpad').style.display = "grid";
  238. document.getElementById('ringing').style.display = "none";
  239. document.getElementById('active').style.display = "none";
  240. //show or hide the buttons
  241. document.getElementById('answer').style.display = "none";
  242. document.getElementById('decline').style.display = "none";
  243. document.getElementById('hangup').style.display = "none";
  244. document.getElementById('local_video').style.display = "none";
  245. document.getElementById('remote_video').style.display = "none";
  246. document.getElementById('mute_audio').style.display = "none";
  247. //document.getElementById('mute_video').style.display = "none";
  248. document.getElementById('unmute_audio').style.display = "none";
  249. //document.getElementById('unmute_video').style.display = "none";
  250. document.getElementById('unhold').style.display = "none";
  251. document.getElementById('hold').style.display = "inline";
  252. //clear the caller ID and timer
  253. document.getElementById('ringing_caller_id').innerHTML = '';
  254. document.getElementById('active_caller_id').innerHTML = '';
  255. document.getElementById('answer_time').innerHTML = '00:00:00';
  256. //mute the audio
  257. //session.mute({audio: true});
  258. }
  259. function hold() {
  260. if (!session) { return; }
  261. document.getElementById('hold').style.display = "none";
  262. document.getElementById('unhold').style.display = "inline";
  263. session.hold();
  264. //session.hold({
  265. // useUpdate: true
  266. //});
  267. }
  268. function unhold() {
  269. if (!session) { return; }
  270. document.getElementById('hold').style.display = "inline";
  271. document.getElementById('unhold').style.display = "none";
  272. session.unhold();
  273. //session.unhold({
  274. // useUpdate: true
  275. //});
  276. }
  277. function send() {
  278. //set the session state
  279. session_hungup = false;
  280. //get the destination number
  281. destination = document.getElementById('destination').value;
  282. //return immediately if there is no destination
  283. if (destination.length == 0) {
  284. return;
  285. }
  286. //show or hide the panels
  287. document.getElementById('dialpad').style.display = "none";
  288. document.getElementById('ringing').style.display = "none";
  289. document.getElementById('active').style.display = "grid";
  290. document.getElementById('answer').style.display = "none";
  291. document.getElementById('decline').style.display = "none";
  292. document.getElementById('hangup').style.display = "inline";
  293. //document.getElementById('local_video').style.display = "inline";
  294. //document.getElementById('remote_video').style.display = "inline";
  295. document.getElementById('mute_audio').style.display = "inline";
  296. //document.getElementById('mute_video').style.display = "inline";
  297. //make a call using a sip invite
  298. session = user_agent.invite('sip:'+destination+'@<?php echo $domain_name; ?>', options);
  299. var remote_video = document.getElementById("remote_video");
  300. remote_video.setAttribute("controls","controls");
  301. //unmute the audio
  302. session.unmute({audio: true});
  303. //start the answer time
  304. answer_time = Date.now();
  305. //set the caller ID to the destination
  306. document.getElementById('ringing_caller_id').innerHTML = destination;
  307. document.getElementById('active_caller_id').innerHTML = destination;
  308. }
  309. function mute_audio(destination) {
  310. if (!session) { return; }
  311. session.mute({audio: true});
  312. document.getElementById('mute_audio').style.display = "none";
  313. document.getElementById('unmute_audio').style.display = "inline";
  314. }
  315. function mute_video(destination) {
  316. if (!session) { return; }
  317. session.mute({video: true});
  318. document.getElementById('local_video').style.display = "none";
  319. document.getElementById('mute_video').style.display = "none";
  320. document.getElementById('unmute_video').style.display = "inline";
  321. }
  322. function unmute_audio(destination) {
  323. if (!session) { return; }
  324. session.unmute({audio: true});
  325. document.getElementById('mute_audio').style.display = "inline";
  326. document.getElementById('unmute_audio').style.display = "none";
  327. }
  328. function unmute_video(destination) {
  329. if (!session) { return; }
  330. session.unmute({video: true});
  331. document.getElementById('local_video').style.display = "inline";
  332. document.getElementById('mute_video').style.display = "inline";
  333. document.getElementById('unmute_video').style.display = "none";
  334. }
  335. //function to center entered digits until full, then right-align and change text direction so last entered digits are always visible
  336. function correct_alignment() {
  337. if (document.getElementById('destination').scrollWidth > document.getElementById('destination').clientWidth) {
  338. document.getElementById('destination').style.textAlign = 'right';
  339. document.getElementById('destination').style.direction = 'rtl';
  340. }
  341. else {
  342. document.getElementById('destination').style.textAlign = 'center';
  343. document.getElementById('destination').style.direction = 'ltr';
  344. }
  345. }
  346. function digit_add($digit) {
  347. document.getElementById('destination').value = document.getElementById('destination').value + $digit;
  348. correct_alignment();
  349. }
  350. function digit_delete() {
  351. destination = document.getElementById('destination').value;
  352. document.getElementById('destination').value = destination.substring(0, destination.length -1);
  353. correct_alignment();
  354. }
  355. function digit_clear() {
  356. document.getElementById('destination').value = '';
  357. correct_alignment();
  358. }
  359. //function to detect numberpad keypresses
  360. document.addEventListener('keyup', function(e) {
  361. if (document.getElementById('destination')) { //destination field is visible
  362. if (
  363. (e.which >= 48 && e.which <= 57) || //numbers
  364. (e.which >= 96 && e.which <= 105) || //number pad
  365. (e.which == 56 || e.which == 106) || //asterisk
  366. (e.which == 51) //pound
  367. ) {
  368. e.preventDefault();
  369. digit_add(e.key);
  370. }
  371. if (e.which == 8 || e.which == 46) { //backspace or delete
  372. e.preventDefault();
  373. digit_delete();
  374. }
  375. if (e.which == 27) { //escape
  376. e.preventDefault();
  377. digit_clear();
  378. }
  379. if (e.which == 13) { //enter
  380. e.preventDefault();
  381. send();
  382. }
  383. }
  384. });
  385. //function to check for Enter key press
  386. function send_enter_key(event) {
  387. if (event.key === "Enter") {
  388. send();
  389. }
  390. }
  391. //add event listener for keydown event on input field
  392. document.addEventListener("DOMContentLoaded", function() {
  393. document.getElementById("destination").addEventListener("keydown", send_enter_key);
  394. });