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.

Toolbar.js 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. /* global APP, $, config, interfaceConfig, JitsiMeetJS */
  2. import UIUtil from '../util/UIUtil';
  3. import UIEvents from '../../../service/UI/UIEvents';
  4. import SideContainerToggler from "../side_pannels/SideContainerToggler";
  5. let emitter = null;
  6. let Toolbar;
  7. /**
  8. * Handlers for toolbar buttons.
  9. *
  10. * buttonId {string}: handler {function}
  11. */
  12. const buttonHandlers = {
  13. "toolbar_button_profile": function () {
  14. JitsiMeetJS.analytics.sendEvent('toolbar.profile.toggled');
  15. emitter.emit(UIEvents.TOGGLE_PROFILE);
  16. },
  17. "toolbar_button_mute": function () {
  18. let sharedVideoManager = APP.UI.getSharedVideoManager();
  19. if (APP.conference.audioMuted) {
  20. // If there's a shared video with the volume "on" and we aren't
  21. // the video owner, we warn the user
  22. // that currently it's not possible to unmute.
  23. if (sharedVideoManager
  24. && sharedVideoManager.isSharedVideoVolumeOn()
  25. && !sharedVideoManager.isSharedVideoOwner()) {
  26. UIUtil.animateShowElement(
  27. $("#unableToUnmutePopup"), true, 5000);
  28. }
  29. else {
  30. JitsiMeetJS.analytics.sendEvent('toolbar.audio.unmuted');
  31. emitter.emit(UIEvents.AUDIO_MUTED, false, true);
  32. }
  33. } else {
  34. JitsiMeetJS.analytics.sendEvent('toolbar.audio.muted');
  35. emitter.emit(UIEvents.AUDIO_MUTED, true, true);
  36. }
  37. },
  38. "toolbar_button_camera": function () {
  39. if (APP.conference.videoMuted) {
  40. JitsiMeetJS.analytics.sendEvent('toolbar.video.enabled');
  41. emitter.emit(UIEvents.VIDEO_MUTED, false);
  42. } else {
  43. JitsiMeetJS.analytics.sendEvent('toolbar.video.disabled');
  44. emitter.emit(UIEvents.VIDEO_MUTED, true);
  45. }
  46. },
  47. "toolbar_button_link": function () {
  48. JitsiMeetJS.analytics.sendEvent('toolbar.invite.clicked');
  49. emitter.emit(UIEvents.INVITE_CLICKED);
  50. },
  51. "toolbar_button_chat": function () {
  52. JitsiMeetJS.analytics.sendEvent('toolbar.chat.toggled');
  53. emitter.emit(UIEvents.TOGGLE_CHAT);
  54. },
  55. "toolbar_contact_list": function () {
  56. JitsiMeetJS.analytics.sendEvent(
  57. 'toolbar.contacts.toggled');
  58. emitter.emit(UIEvents.TOGGLE_CONTACT_LIST);
  59. },
  60. "toolbar_button_etherpad": function () {
  61. JitsiMeetJS.analytics.sendEvent('toolbar.etherpad.clicked');
  62. emitter.emit(UIEvents.ETHERPAD_CLICKED);
  63. },
  64. "toolbar_button_sharedvideo": function () {
  65. JitsiMeetJS.analytics.sendEvent('toolbar.sharedvideo.clicked');
  66. emitter.emit(UIEvents.SHARED_VIDEO_CLICKED);
  67. },
  68. "toolbar_button_desktopsharing": function () {
  69. if (APP.conference.isSharingScreen) {
  70. JitsiMeetJS.analytics.sendEvent('toolbar.screen.disabled');
  71. } else {
  72. JitsiMeetJS.analytics.sendEvent('toolbar.screen.enabled');
  73. }
  74. emitter.emit(UIEvents.TOGGLE_SCREENSHARING);
  75. },
  76. "toolbar_button_fullScreen": function() {
  77. JitsiMeetJS.analytics.sendEvent('toolbar.fullscreen.enabled');
  78. emitter.emit(UIEvents.TOGGLE_FULLSCREEN);
  79. },
  80. "toolbar_button_sip": function () {
  81. JitsiMeetJS.analytics.sendEvent('toolbar.sip.clicked');
  82. showSipNumberInput();
  83. },
  84. "toolbar_button_dialpad": function () {
  85. JitsiMeetJS.analytics.sendEvent('toolbar.sip.dialpad.clicked');
  86. dialpadButtonClicked();
  87. },
  88. "toolbar_button_settings": function () {
  89. JitsiMeetJS.analytics.sendEvent('toolbar.settings.toggled');
  90. emitter.emit(UIEvents.TOGGLE_SETTINGS);
  91. },
  92. "toolbar_button_hangup": function () {
  93. JitsiMeetJS.analytics.sendEvent('toolbar.hangup');
  94. emitter.emit(UIEvents.HANGUP);
  95. },
  96. "toolbar_button_raisehand": function () {
  97. JitsiMeetJS.analytics.sendEvent('toolbar.raiseHand.clicked');
  98. APP.conference.maybeToggleRaisedHand();
  99. }
  100. };
  101. /**
  102. * All toolbars buttons description
  103. */
  104. const defaultToolbarButtons = {
  105. 'microphone': {
  106. id: 'toolbar_button_mute',
  107. tooltipKey: 'toolbar.mute',
  108. className: "button icon-microphone",
  109. shortcut: 'M',
  110. shortcutAttr: 'mutePopover',
  111. shortcutFunc: function() {
  112. JitsiMeetJS.analytics.sendEvent('shortcut.audiomute.toggled');
  113. APP.conference.toggleAudioMuted();
  114. },
  115. shortcutDescription: "keyboardShortcuts.mute",
  116. popups: [
  117. {
  118. id: "micMutedPopup",
  119. className: "loginmenu",
  120. dataAttr: "[html]toolbar.micMutedPopup"
  121. },
  122. {
  123. id: "unableToUnmutePopup",
  124. className: "loginmenu",
  125. dataAttr: "[html]toolbar.unableToUnmutePopup"
  126. },
  127. {
  128. id: "talkWhileMutedPopup",
  129. className: "loginmenu",
  130. dataAttr: "[html]toolbar.talkWhileMutedPopup"
  131. }
  132. ],
  133. content: "Mute / Unmute",
  134. i18n: "[content]toolbar.mute"
  135. },
  136. 'camera': {
  137. id: 'toolbar_button_camera',
  138. tooltipKey: 'toolbar.videomute',
  139. className: "button icon-camera",
  140. shortcut: 'V',
  141. shortcutAttr: 'toggleVideoPopover',
  142. shortcutFunc: function() {
  143. JitsiMeetJS.analytics.sendEvent('shortcut.videomute.toggled');
  144. APP.conference.toggleVideoMuted();
  145. },
  146. shortcutDescription: "keyboardShortcuts.videoMute",
  147. content: "Start / stop camera",
  148. i18n: "[content]toolbar.videomute"
  149. },
  150. 'desktop': {
  151. id: 'toolbar_button_desktopsharing',
  152. tooltipKey: 'toolbar.sharescreen',
  153. className: 'button icon-share-desktop',
  154. shortcut: 'D',
  155. shortcutAttr: 'toggleDesktopSharingPopover',
  156. shortcutFunc: function() {
  157. JitsiMeetJS.analytics.sendEvent('shortcut.screen.toggled');
  158. APP.conference.toggleScreenSharing();
  159. },
  160. shortcutDescription: 'keyboardShortcuts.toggleScreensharing',
  161. content: 'Share screen',
  162. i18n: '[content]toolbar.sharescreen'
  163. },
  164. 'invite': {
  165. id: 'toolbar_button_link',
  166. tooltipKey: 'toolbar.invite',
  167. className: 'button icon-link',
  168. content: 'Invite others',
  169. i18n: '[content]toolbar.invite'
  170. },
  171. 'chat': {
  172. id: 'toolbar_button_chat',
  173. tooltipKey: 'toolbar.chat',
  174. className: 'button icon-chat',
  175. shortcut: 'C',
  176. shortcutAttr: 'toggleChatPopover',
  177. shortcutFunc: function() {
  178. JitsiMeetJS.analytics.sendEvent('shortcut.chat.toggled');
  179. APP.UI.toggleChat();
  180. },
  181. shortcutDescription: 'keyboardShortcuts.toggleChat',
  182. sideContainerId: 'chat_container',
  183. html: `<span class="badge-round">
  184. <span id="unreadMessages"></span>
  185. </span>`
  186. },
  187. 'contacts': {
  188. id: 'toolbar_contact_list',
  189. tooltipKey: 'bottomtoolbar.contactlist',
  190. className: 'button icon-contactList',
  191. sideContainerId: 'contacts_container',
  192. html: `<span class="badge-round">
  193. <span id="numberOfParticipants"></span>
  194. </span>`
  195. },
  196. 'profile': {
  197. id: 'toolbar_button_profile',
  198. tooltipKey: 'profile.setDisplayNameLabel',
  199. className: 'button',
  200. sideContainerId: 'profile_container',
  201. html: `<img id="avatar" src="images/avatar2.png"/>`
  202. },
  203. 'etherpad': {
  204. id: 'toolbar_button_etherpad',
  205. tooltipKey: 'toolbar.etherpad',
  206. className: 'button icon-share-doc'
  207. },
  208. 'fullscreen': {
  209. id: 'toolbar_button_fullScreen',
  210. tooltipKey: 'toolbar.fullscreen',
  211. className: "button icon-full-screen",
  212. shortcut: 'S',
  213. shortcutAttr: 'toggleFullscreenPopover',
  214. shortcutFunc: function() {
  215. JitsiMeetJS.analytics.sendEvent('shortcut.fullscreen.toggled');
  216. APP.UI.toggleFullScreen();
  217. },
  218. shortcutDescription: "keyboardShortcuts.fullScreen",
  219. content: "Enter / Exit Full Screen",
  220. i18n: "[content]toolbar.fullscreen"
  221. },
  222. 'settings': {
  223. id: 'toolbar_button_settings',
  224. tooltipKey: 'toolbar.Settings',
  225. className: 'button icon-settings',
  226. sideContainerId: "settings_container"
  227. },
  228. 'hangup': {
  229. id: 'toolbar_button_hangup',
  230. tooltipKey: 'toolbar.hangup',
  231. className: "button icon-hangup",
  232. content: "Hang Up",
  233. i18n: "[content]toolbar.hangup"
  234. },
  235. 'raisehand': {
  236. id: "toolbar_button_raisehand",
  237. tooltipKey: 'toolbar.raiseHand',
  238. className: "button icon-raised-hand",
  239. shortcut: "R",
  240. shortcutAttr: "raiseHandPopover",
  241. shortcutFunc: function() {
  242. JitsiMeetJS.analytics.sendEvent("shortcut.raisehand.clicked");
  243. APP.conference.maybeToggleRaisedHand();
  244. },
  245. shortcutDescription: "keyboardShortcuts.raiseHand",
  246. content: "Raise Hand",
  247. i18n: "[content]toolbar.raiseHand"
  248. },
  249. //init and btn handler: Recording.initRecordingButton (Recording.js)
  250. 'recording': {
  251. id: 'toolbar_button_record',
  252. tooltipKey: 'liveStreaming.buttonTooltip',
  253. className: 'button',
  254. hidden: true // will be displayed once
  255. // the recording functionality is detected
  256. },
  257. 'sharedvideo': {
  258. id: 'toolbar_button_sharedvideo',
  259. tooltipKey: 'toolbar.sharedvideo',
  260. className: 'button icon-shared-video',
  261. html: `<ul id="sharedVideoMutedPopup"
  262. class="loginmenu extendedToolbarPopup">
  263. <li data-i18n="[html]toolbar.sharedVideoMutedPopup"></li>
  264. </ul>
  265. `
  266. },
  267. 'sip': {
  268. id: 'toolbar_button_sip',
  269. tooltipKey: 'toolbar.sip',
  270. className: 'button icon-telephone',
  271. hidden: true // will be displayed once
  272. // the SIP calls functionality is detected
  273. },
  274. 'dialpad': {
  275. id: 'toolbar_button_dialpad',
  276. tooltipKey: 'toolbar.dialpad',
  277. className: 'button icon-dialpad',
  278. //TODO: remove it after UI.updateDTMFSupport fix
  279. hidden: true
  280. }
  281. };
  282. function dialpadButtonClicked() {
  283. //TODO show the dialpad box
  284. }
  285. function showSipNumberInput () {
  286. let defaultNumber = config.defaultSipNumber
  287. ? config.defaultSipNumber
  288. : '';
  289. let titleKey = "dialog.sipMsg";
  290. let msgString = (`
  291. <input class="input-control"
  292. name="sipNumber" type="text"
  293. value="${defaultNumber}" autofocus>`);
  294. APP.UI.messageHandler.openTwoButtonDialog({
  295. titleKey,
  296. msgString,
  297. leftButtonKey: "dialog.Dial",
  298. submitFunction: function (e, v, m, f) {
  299. if (v && f.sipNumber) {
  300. emitter.emit(UIEvents.SIP_DIAL, f.sipNumber);
  301. }
  302. },
  303. focus: ':input:first'
  304. });
  305. }
  306. /**
  307. * Get place for toolbar button.
  308. * Now it can be in main toolbar or in extended (left) toolbar
  309. *
  310. * @param btn {string}
  311. * @returns {string}
  312. */
  313. function getToolbarButtonPlace (btn) {
  314. return interfaceConfig.MAIN_TOOLBAR_BUTTONS.includes(btn) ?
  315. 'main' :
  316. 'extended';
  317. }
  318. Toolbar = {
  319. init (eventEmitter) {
  320. emitter = eventEmitter;
  321. // The toolbar is enabled by default.
  322. this.enabled = true;
  323. this.toolbarSelector = $("#mainToolbarContainer");
  324. this.extendedToolbarSelector = $("#extendedToolbar");
  325. // Initialise the toolbar buttons.
  326. // The main toolbar will only take into account
  327. // it's own configuration from interface_config.
  328. this._initToolbarButtons();
  329. this._setShortcutsAndTooltips();
  330. this._setButtonHandlers();
  331. APP.UI.addListener(UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
  332. (containerId, isVisible) => {
  333. Toolbar._handleSideToolbarContainerToggled( containerId,
  334. isVisible);
  335. });
  336. APP.UI.addListener(UIEvents.LOCAL_RAISE_HAND_CHANGED,
  337. (isRaisedHand) => {
  338. this._setToggledState("toolbar_button_raisehand", isRaisedHand);
  339. });
  340. APP.UI.addListener(UIEvents.FULLSCREEN_TOGGLED,
  341. (isFullScreen) => {
  342. Toolbar._handleFullScreenToggled(isFullScreen);
  343. });
  344. if(!APP.tokenData.isGuest) {
  345. $("#toolbar_button_profile").addClass("unclickable");
  346. UIUtil.removeTooltip(
  347. document.getElementById('toolbar_button_profile'));
  348. }
  349. },
  350. /**
  351. * Enables / disables the toolbar.
  352. * @param {e} set to {true} to enable the toolbar or {false}
  353. * to disable it
  354. */
  355. enable (e) {
  356. this.enabled = e;
  357. if (!e && this.isVisible())
  358. this.hide(false);
  359. },
  360. /**
  361. * Indicates if the bottom toolbar is currently enabled.
  362. * @return {this.enabled}
  363. */
  364. isEnabled() {
  365. return this.enabled;
  366. },
  367. showEtherpadButton () {
  368. if (!$('#toolbar_button_etherpad').is(":visible")) {
  369. $('#toolbar_button_etherpad').css({display: 'inline-block'});
  370. }
  371. },
  372. // Shows or hides the 'shared video' button.
  373. showSharedVideoButton () {
  374. let id = 'toolbar_button_sharedvideo';
  375. let shouldShow = UIUtil.isButtonEnabled('sharedvideo')
  376. && !config.disableThirdPartyRequests;
  377. if (shouldShow) {
  378. let el = document.getElementById(id);
  379. UIUtil.setTooltip(el, 'toolbar.sharedvideo', 'right');
  380. }
  381. UIUtil.setVisible(id, shouldShow);
  382. },
  383. // checks whether desktop sharing is enabled and whether
  384. // we have params to start automatically sharing
  385. checkAutoEnableDesktopSharing () {
  386. if (UIUtil.isButtonEnabled('desktop')
  387. && config.autoEnableDesktopSharing) {
  388. emitter.emit(UIEvents.TOGGLE_SCREENSHARING);
  389. }
  390. },
  391. // Shows or hides SIP calls button
  392. showSipCallButton (show) {
  393. let shouldShow = APP.conference.sipGatewayEnabled()
  394. && UIUtil.isButtonEnabled('sip') && show;
  395. let id = 'toolbar_button_sip';
  396. UIUtil.setVisible(id, shouldShow);
  397. },
  398. // Shows or hides the dialpad button
  399. showDialPadButton (show) {
  400. let shouldShow = UIUtil.isButtonEnabled('dialpad') && show;
  401. let id = 'toolbar_button_dialpad';
  402. UIUtil.setVisible(id, shouldShow);
  403. },
  404. /**
  405. * Update the state of the button. The button has blue glow if desktop
  406. * streaming is active.
  407. */
  408. updateDesktopSharingButtonState () {
  409. this._setToggledState( "toolbar_button_desktopsharing",
  410. APP.conference.isSharingScreen);
  411. },
  412. /**
  413. * Marks video icon as muted or not.
  414. *
  415. * @param {boolean} muted if icon should look like muted or not
  416. */
  417. toggleVideoIcon (muted) {
  418. $('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
  419. this._setToggledState("toolbar_button_camera", muted);
  420. },
  421. /**
  422. * Enables / disables audio toolbar button.
  423. *
  424. * @param {boolean} enabled indicates if the button should be enabled
  425. * or disabled
  426. */
  427. setVideoIconEnabled (enabled) {
  428. this._setMediaIconEnabled(
  429. '#toolbar_button_camera',
  430. enabled,
  431. /* data-i18n attribute value */
  432. `[content]toolbar.${enabled ? 'videomute' : 'cameraDisabled'}`,
  433. /* shortcut attribute value */
  434. 'toggleVideoPopover');
  435. enabled || this.toggleVideoIcon(!enabled);
  436. },
  437. /**
  438. * Enables/disables the toolbar button associated with a specific media such
  439. * as audio or video.
  440. *
  441. * @param {string} btn - The jQuery selector <tt>string</tt> which
  442. * identifies the toolbar button to be enabled/disabled.
  443. * @param {boolean} enabled - <tt>true</tt> to enable the specified
  444. * <tt>btn</tt> or <tt>false</tt> to disable it.
  445. * @param {string} dataI18n - The value to assign to the <tt>data-i18n</tt>
  446. * attribute of the specified <tt>btn</tt>.
  447. * @param {string} shortcut - The value, if any, to assign to the
  448. * <tt>shortcut</tt> attribute of the specified <tt>btn</tt> if the toolbar
  449. * button is enabled.
  450. */
  451. _setMediaIconEnabled(btn, enabled, dataI18n, shortcut) {
  452. const $btn = $(btn);
  453. $btn
  454. .prop('disabled', !enabled)
  455. .attr('data-i18n', dataI18n)
  456. .attr('shortcut', enabled && shortcut ? shortcut : '');
  457. enabled
  458. ? $btn.removeAttr('disabled')
  459. : $btn.attr('disabled', 'disabled');
  460. APP.translation.translateElement($btn);
  461. },
  462. /**
  463. * Marks audio icon as muted or not.
  464. *
  465. * @param {boolean} muted if icon should look like muted or not
  466. */
  467. toggleAudioIcon(muted) {
  468. $('#toolbar_button_mute')
  469. .toggleClass("icon-microphone", !muted)
  470. .toggleClass("icon-mic-disabled", muted);
  471. this._setToggledState("toolbar_button_mute", muted);
  472. },
  473. /**
  474. * Enables / disables audio toolbar button.
  475. *
  476. * @param {boolean} enabled indicates if the button should be enabled
  477. * or disabled
  478. */
  479. setAudioIconEnabled (enabled) {
  480. this._setMediaIconEnabled(
  481. '#toolbar_button_mute',
  482. enabled,
  483. /* data-i18n attribute value */
  484. `[content]toolbar.${enabled ? 'mute' : 'micDisabled'}`,
  485. /* shortcut attribute value */
  486. 'mutePopover');
  487. enabled || this.toggleAudioIcon(!enabled);
  488. },
  489. /**
  490. * Indicates if the toolbar is currently hovered.
  491. * @return {boolean} true if the toolbar is currently hovered,
  492. * false otherwise
  493. */
  494. isHovered() {
  495. var hovered = false;
  496. this.toolbarSelector.find('*').each(function () {
  497. let id = $(this).attr('id');
  498. if ($(`#${id}:hover`).length > 0) {
  499. hovered = true;
  500. // break each
  501. return false;
  502. }
  503. });
  504. if (hovered)
  505. return true;
  506. if ($("#bottomToolbar:hover").length > 0
  507. || $("#extendedToolbar:hover").length > 0
  508. || SideContainerToggler.isHovered()) {
  509. return true;
  510. }
  511. return false;
  512. },
  513. /**
  514. * Returns true if this toolbar is currently visible, or false otherwise.
  515. * @return <tt>true</tt> if currently visible, <tt>false</tt> - otherwise
  516. */
  517. isVisible() {
  518. return this.toolbarSelector.hasClass("fadeIn");
  519. },
  520. /**
  521. * Hides the toolbar with animation or not depending on the animate
  522. * parameter.
  523. */
  524. hide() {
  525. this.toolbarSelector
  526. .removeClass("fadeIn")
  527. .addClass("fadeOut");
  528. let slideInAnimation = (SideContainerToggler.isVisible)
  529. ? "slideInExtX"
  530. : "slideInX";
  531. let slideOutAnimation = (SideContainerToggler.isVisible)
  532. ? "slideOutExtX"
  533. : "slideOutX";
  534. this.extendedToolbarSelector.toggleClass(slideInAnimation)
  535. .toggleClass(slideOutAnimation);
  536. },
  537. /**
  538. * Shows the toolbar with animation or not depending on the animate
  539. * parameter.
  540. */
  541. show() {
  542. if (this.toolbarSelector.hasClass("fadeOut")) {
  543. this.toolbarSelector.removeClass("fadeOut");
  544. }
  545. let slideInAnimation = (SideContainerToggler.isVisible)
  546. ? "slideInExtX"
  547. : "slideInX";
  548. let slideOutAnimation = (SideContainerToggler.isVisible)
  549. ? "slideOutExtX"
  550. : "slideOutX";
  551. if (this.extendedToolbarSelector.hasClass(slideOutAnimation)) {
  552. this.extendedToolbarSelector.toggleClass(slideOutAnimation);
  553. }
  554. this.toolbarSelector.addClass("fadeIn");
  555. this.extendedToolbarSelector.toggleClass(slideInAnimation);
  556. },
  557. registerClickListeners(listener) {
  558. $('#mainToolbarContainer').click(listener);
  559. $("#extendedToolbar").click(listener);
  560. },
  561. /**
  562. * Handles the side toolbar toggle.
  563. *
  564. * @param {string} containerId the identifier of the container element
  565. */
  566. _handleSideToolbarContainerToggled(containerId) {
  567. Object.keys(defaultToolbarButtons).forEach(
  568. id => {
  569. if (!UIUtil.isButtonEnabled(id))
  570. return;
  571. var button = defaultToolbarButtons[id];
  572. if (button.sideContainerId
  573. && button.sideContainerId === containerId) {
  574. UIUtil.buttonClick(button.id, "selected");
  575. return;
  576. }
  577. }
  578. );
  579. },
  580. /**
  581. * Handles full screen toggled.
  582. *
  583. * @param {boolean} isFullScreen indicates if we're currently in full
  584. * screen mode
  585. */
  586. _handleFullScreenToggled(isFullScreen) {
  587. let element
  588. = document.getElementById("toolbar_button_fullScreen");
  589. element.className = isFullScreen
  590. ? element.className
  591. .replace("icon-full-screen", "icon-exit-full-screen")
  592. : element.className
  593. .replace("icon-exit-full-screen", "icon-full-screen");
  594. Toolbar._setToggledState("toolbar_button_fullScreen", isFullScreen);
  595. },
  596. /**
  597. * Initialise toolbar buttons.
  598. */
  599. _initToolbarButtons() {
  600. interfaceConfig.TOOLBAR_BUTTONS.forEach((value, index) => {
  601. let place = getToolbarButtonPlace(value);
  602. if (value && value in defaultToolbarButtons) {
  603. let button = defaultToolbarButtons[value];
  604. this._addToolbarButton(
  605. button,
  606. place,
  607. (interfaceConfig.MAIN_TOOLBAR_SPLITTER_INDEX !== undefined
  608. && index
  609. === interfaceConfig.MAIN_TOOLBAR_SPLITTER_INDEX));
  610. }
  611. });
  612. },
  613. /**
  614. * Adds the given button to the main (top) or extended (left) toolbar.
  615. *
  616. * @param {Object} the button to add.
  617. * @param {boolean} isFirst indicates if this is the first button in the
  618. * toolbar
  619. * @param {boolean} isLast indicates if this is the last button in the
  620. * toolbar
  621. * @param {boolean} isSplitter if this button is a splitter button for
  622. * the dialog, which means that a special splitter style will be applied
  623. */
  624. _addToolbarButton(button, place, isSplitter) {
  625. const places = {
  626. main: 'mainToolbar',
  627. extended: 'extendedToolbarButtons'
  628. };
  629. let id = places[place];
  630. let buttonElement = document.createElement("a");
  631. if (button.className) {
  632. buttonElement.className = button.className;
  633. }
  634. if (isSplitter) {
  635. let splitter = document.createElement('span');
  636. splitter.className = 'toolbar__splitter';
  637. document.getElementById(id).appendChild(splitter);
  638. }
  639. buttonElement.id = button.id;
  640. if (button.html)
  641. buttonElement.innerHTML = button.html;
  642. //TODO: remove it after UI.updateDTMFSupport fix
  643. if (button.hidden)
  644. buttonElement.style.display = 'none';
  645. if (button.shortcutAttr)
  646. buttonElement.setAttribute("shortcut", button.shortcutAttr);
  647. if (button.content)
  648. buttonElement.setAttribute("content", button.content);
  649. if (button.i18n)
  650. buttonElement.setAttribute("data-i18n", button.i18n);
  651. buttonElement.setAttribute("data-container", "body");
  652. buttonElement.setAttribute("data-placement", "bottom");
  653. this._addPopups(buttonElement, button.popups);
  654. document.getElementById(id)
  655. .appendChild(buttonElement);
  656. },
  657. _addPopups(buttonElement, popups = []) {
  658. popups.forEach((popup) => {
  659. let popupElement = document.createElement("ul");
  660. popupElement.id = popup.id;
  661. popupElement.className = popup.className;
  662. let liElement = document.createElement("li");
  663. liElement.setAttribute("data-i18n", popup.dataAttr);
  664. popupElement.appendChild(liElement);
  665. buttonElement.appendChild(popupElement);
  666. });
  667. },
  668. /**
  669. * Sets the toggled state of the given element depending on the isToggled
  670. * parameter.
  671. *
  672. * @param elementId the element identifier
  673. * @param isToggled indicates if the element should be toggled or untoggled
  674. */
  675. _setToggledState(elementId, isToggled) {
  676. $("#" + elementId).toggleClass("toggled", isToggled);
  677. },
  678. /**
  679. * Sets Shortcuts and Tooltips for all toolbar buttons
  680. *
  681. * @private
  682. */
  683. _setShortcutsAndTooltips() {
  684. Object.keys(defaultToolbarButtons).forEach(
  685. id => {
  686. if (UIUtil.isButtonEnabled(id)) {
  687. let button = defaultToolbarButtons[id];
  688. let buttonElement = document.getElementById(button.id);
  689. if (!buttonElement) return false;
  690. let tooltipPosition
  691. = (interfaceConfig.MAIN_TOOLBAR_BUTTONS
  692. .indexOf(id) > -1)
  693. ? "bottom" : "right";
  694. UIUtil.setTooltip( buttonElement,
  695. button.tooltipKey,
  696. tooltipPosition);
  697. if (button.shortcut)
  698. APP.keyboardshortcut.registerShortcut(
  699. button.shortcut,
  700. button.shortcutAttr,
  701. button.shortcutFunc,
  702. button.shortcutDescription
  703. );
  704. }
  705. }
  706. );
  707. },
  708. /**
  709. * Sets Handlers for all toolbar buttons
  710. *
  711. * @private
  712. */
  713. _setButtonHandlers() {
  714. Object.keys(buttonHandlers).forEach(
  715. buttonId => $(`#${buttonId}`).click(function(event) {
  716. !$(this).prop('disabled') && buttonHandlers[buttonId](event);
  717. })
  718. );
  719. }
  720. };
  721. export default Toolbar;