Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Toolbar.js 28KB

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