您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Toolbar.js 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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 class="input-control"
  308. name="sipNumber" type="text"
  309. value="${defaultNumber}" autofocus>`);
  310. APP.UI.messageHandler.openTwoButtonDialog({
  311. titleKey,
  312. msgString,
  313. leftButtonKey: "dialog.Dial",
  314. submitFunction: function (e, v, m, f) {
  315. if (v && f.sipNumber) {
  316. emitter.emit(UIEvents.SIP_DIAL, f.sipNumber);
  317. }
  318. },
  319. focus: ':input:first'
  320. });
  321. }
  322. /**
  323. * Get place for toolbar button.
  324. * Now it can be in main toolbar or in extended (left) toolbar
  325. *
  326. * @param btn {string}
  327. * @returns {string}
  328. */
  329. function getToolbarButtonPlace (btn) {
  330. return interfaceConfig.MAIN_TOOLBAR_BUTTONS.includes(btn) ?
  331. 'main' :
  332. 'extended';
  333. }
  334. Toolbar = {
  335. init (eventEmitter) {
  336. emitter = eventEmitter;
  337. // The toolbar is enabled by default.
  338. this.enabled = true;
  339. this.toolbarSelector = $("#mainToolbarContainer");
  340. this.extendedToolbarSelector = $("#extendedToolbar");
  341. // Initialise the toolbar buttons.
  342. // The main toolbar will only take into account
  343. // it's own configuration from interface_config.
  344. this._initToolbarButtons();
  345. this._setShortcutsAndTooltips();
  346. this._setButtonHandlers();
  347. APP.UI.addListener(UIEvents.SIDE_TOOLBAR_CONTAINER_TOGGLED,
  348. (containerId, isVisible) => {
  349. Toolbar._handleSideToolbarContainerToggled( containerId,
  350. isVisible);
  351. });
  352. APP.UI.addListener(UIEvents.LOCAL_RAISE_HAND_CHANGED,
  353. (isRaisedHand) => {
  354. this._setToggledState("toolbar_button_raisehand", isRaisedHand);
  355. });
  356. APP.UI.addListener(UIEvents.FULLSCREEN_TOGGLED,
  357. (isFullScreen) => {
  358. Toolbar._handleFullScreenToggled(isFullScreen);
  359. });
  360. if(!APP.tokenData.isGuest) {
  361. $("#toolbar_button_profile").addClass("unclickable");
  362. UIUtil.removeTooltip(
  363. document.getElementById('toolbar_button_profile'));
  364. }
  365. },
  366. /**
  367. * Enables / disables the toolbar.
  368. * @param {e} set to {true} to enable the toolbar or {false}
  369. * to disable it
  370. */
  371. enable (e) {
  372. this.enabled = e;
  373. if (!e && this.isVisible())
  374. this.hide(false);
  375. },
  376. /**
  377. * Indicates if the bottom toolbar is currently enabled.
  378. * @return {this.enabled}
  379. */
  380. isEnabled() {
  381. return this.enabled;
  382. },
  383. /**
  384. * Shows or hides authentication button
  385. * @param show <tt>true</tt> to show or <tt>false</tt> to hide
  386. */
  387. showAuthenticateButton (show) {
  388. let id = 'authenticationContainer';
  389. UIUtil.showOrHideElement(id, show);
  390. },
  391. showEtherpadButton () {
  392. if (!$('#toolbar_button_etherpad').is(":visible")) {
  393. $('#toolbar_button_etherpad').css({display: 'inline-block'});
  394. }
  395. },
  396. // Shows or hides the 'shared video' button.
  397. showSharedVideoButton () {
  398. let id = 'toolbar_button_sharedvideo';
  399. let shouldShow = UIUtil.isButtonEnabled('sharedvideo')
  400. && !config.disableThirdPartyRequests;
  401. if (shouldShow) {
  402. let el = document.getElementById(id);
  403. UIUtil.setTooltip(el, 'toolbar.sharedvideo', 'right');
  404. }
  405. UIUtil.showOrHideElement(id, shouldShow);
  406. },
  407. // checks whether desktop sharing is enabled and whether
  408. // we have params to start automatically sharing
  409. checkAutoEnableDesktopSharing () {
  410. if (UIUtil.isButtonEnabled('desktop')
  411. && config.autoEnableDesktopSharing) {
  412. emitter.emit(UIEvents.TOGGLE_SCREENSHARING);
  413. }
  414. },
  415. // Shows or hides SIP calls button
  416. showSipCallButton (show) {
  417. let shouldShow = APP.conference.sipGatewayEnabled()
  418. && UIUtil.isButtonEnabled('sip') && show;
  419. let id = 'toolbar_button_sip';
  420. UIUtil.showOrHideElement(id, shouldShow);
  421. },
  422. // Shows or hides the dialpad button
  423. showDialPadButton (show) {
  424. let shouldShow = UIUtil.isButtonEnabled('dialpad') && show;
  425. let id = 'toolbar_button_dialpad';
  426. UIUtil.showOrHideElement(id, shouldShow);
  427. },
  428. /**
  429. * Displays user authenticated identity name(login).
  430. * @param authIdentity identity name to be displayed.
  431. */
  432. setAuthenticatedIdentity (authIdentity) {
  433. let id = 'toolbar_auth_identity';
  434. if(authIdentity) {
  435. $(`#${id}`).text(authIdentity);
  436. } else {
  437. $(`#${id}`).text('');
  438. }
  439. UIUtil.showOrHideElement(id, !!authIdentity);
  440. },
  441. /**
  442. * Shows/hides login button.
  443. * @param show <tt>true</tt> to show
  444. */
  445. showLoginButton (show) {
  446. let id = 'toolbar_button_login';
  447. UIUtil.showOrHideElement(id, show);
  448. },
  449. /**
  450. * Shows/hides logout button.
  451. * @param show <tt>true</tt> to show
  452. */
  453. showLogoutButton (show) {
  454. let id = 'toolbar_button_logout';
  455. UIUtil.showOrHideElement(id, show);
  456. },
  457. /**
  458. * Update the state of the button. The button has blue glow if desktop
  459. * streaming is active.
  460. */
  461. updateDesktopSharingButtonState () {
  462. this._setToggledState( "toolbar_button_desktopsharing",
  463. APP.conference.isSharingScreen);
  464. },
  465. /**
  466. * Marks video icon as muted or not.
  467. *
  468. * @param {boolean} muted if icon should look like muted or not
  469. */
  470. toggleVideoIcon (muted) {
  471. $('#toolbar_button_camera').toggleClass("icon-camera-disabled", muted);
  472. this._setToggledState("toolbar_button_camera", muted);
  473. },
  474. /**
  475. * Enables / disables audio toolbar button.
  476. *
  477. * @param {boolean} enabled indicates if the button should be enabled
  478. * or disabled
  479. */
  480. setVideoIconEnabled (enabled) {
  481. this._setMediaIconEnabled(
  482. '#toolbar_button_camera',
  483. enabled,
  484. /* data-i18n attribute value */
  485. `[content]toolbar.${enabled ? 'videomute' : 'cameraDisabled'}`,
  486. /* shortcut attribute value */
  487. 'toggleVideoPopover');
  488. enabled || this.toggleVideoIcon(!enabled);
  489. },
  490. /**
  491. * Enables/disables the toolbar button associated with a specific media such
  492. * as audio or video.
  493. *
  494. * @param {string} btn - The jQuery selector <tt>string</tt> which
  495. * identifies the toolbar button to be enabled/disabled.
  496. * @param {boolean} enabled - <tt>true</tt> to enable the specified
  497. * <tt>btn</tt> or <tt>false</tt> to disable it.
  498. * @param {string} dataI18n - The value to assign to the <tt>data-i18n</tt>
  499. * attribute of the specified <tt>btn</tt>.
  500. * @param {string} shortcut - The value, if any, to assign to the
  501. * <tt>shortcut</tt> attribute of the specified <tt>btn</tt> if the toolbar
  502. * button is enabled.
  503. */
  504. _setMediaIconEnabled(btn, enabled, dataI18n, shortcut) {
  505. const $btn = $(btn);
  506. $btn
  507. .prop('disabled', !enabled)
  508. .attr('data-i18n', dataI18n)
  509. .attr('shortcut', enabled && shortcut ? shortcut : '');
  510. enabled
  511. ? $btn.removeAttr('disabled')
  512. : $btn.attr('disabled', 'disabled');
  513. APP.translation.translateElement($btn);
  514. },
  515. /**
  516. * Marks audio icon as muted or not.
  517. *
  518. * @param {boolean} muted if icon should look like muted or not
  519. */
  520. toggleAudioIcon(muted) {
  521. $('#toolbar_button_mute')
  522. .toggleClass("icon-microphone", !muted)
  523. .toggleClass("icon-mic-disabled", muted);
  524. this._setToggledState("toolbar_button_mute", muted);
  525. },
  526. /**
  527. * Enables / disables audio toolbar button.
  528. *
  529. * @param {boolean} enabled indicates if the button should be enabled
  530. * or disabled
  531. */
  532. setAudioIconEnabled (enabled) {
  533. this._setMediaIconEnabled(
  534. '#toolbar_button_mute',
  535. enabled,
  536. /* data-i18n attribute value */
  537. `[content]toolbar.${enabled ? 'mute' : 'micDisabled'}`,
  538. /* shortcut attribute value */
  539. 'mutePopover');
  540. enabled || this.toggleAudioIcon(!enabled);
  541. },
  542. /**
  543. * Indicates if the toolbar is currently hovered.
  544. * @return {boolean} true if the toolbar is currently hovered,
  545. * false otherwise
  546. */
  547. isHovered() {
  548. var hovered = false;
  549. this.toolbarSelector.find('*').each(function () {
  550. let id = $(this).attr('id');
  551. if ($(`#${id}:hover`).length > 0) {
  552. hovered = true;
  553. // break each
  554. return false;
  555. }
  556. });
  557. if (hovered)
  558. return true;
  559. if ($("#bottomToolbar:hover").length > 0
  560. || $("#extendedToolbar:hover").length > 0
  561. || SideContainerToggler.isHovered()) {
  562. return true;
  563. }
  564. return false;
  565. },
  566. /**
  567. * Returns true if this toolbar is currently visible, or false otherwise.
  568. * @return <tt>true</tt> if currently visible, <tt>false</tt> - otherwise
  569. */
  570. isVisible() {
  571. return this.toolbarSelector.hasClass("fadeIn");
  572. },
  573. /**
  574. * Hides the toolbar with animation or not depending on the animate
  575. * parameter.
  576. */
  577. hide() {
  578. this.toolbarSelector
  579. .removeClass("fadeIn")
  580. .addClass("fadeOut");
  581. let slideInAnimation = (SideContainerToggler.isVisible)
  582. ? "slideInExtX"
  583. : "slideInX";
  584. let slideOutAnimation = (SideContainerToggler.isVisible)
  585. ? "slideOutExtX"
  586. : "slideOutX";
  587. this.extendedToolbarSelector.toggleClass(slideInAnimation)
  588. .toggleClass(slideOutAnimation);
  589. },
  590. /**
  591. * Shows the toolbar with animation or not depending on the animate
  592. * parameter.
  593. */
  594. show() {
  595. if (this.toolbarSelector.hasClass("fadeOut")) {
  596. this.toolbarSelector.removeClass("fadeOut");
  597. }
  598. let slideInAnimation = (SideContainerToggler.isVisible)
  599. ? "slideInExtX"
  600. : "slideInX";
  601. let slideOutAnimation = (SideContainerToggler.isVisible)
  602. ? "slideOutExtX"
  603. : "slideOutX";
  604. if (this.extendedToolbarSelector.hasClass(slideOutAnimation)) {
  605. this.extendedToolbarSelector.toggleClass(slideOutAnimation);
  606. }
  607. this.toolbarSelector.addClass("fadeIn");
  608. this.extendedToolbarSelector.toggleClass(slideInAnimation);
  609. },
  610. registerClickListeners(listener) {
  611. $('#mainToolbarContainer').click(listener);
  612. $("#extendedToolbar").click(listener);
  613. },
  614. /**
  615. * Handles the side toolbar toggle.
  616. *
  617. * @param {string} containerId the identifier of the container element
  618. */
  619. _handleSideToolbarContainerToggled(containerId) {
  620. Object.keys(defaultToolbarButtons).forEach(
  621. id => {
  622. if (!UIUtil.isButtonEnabled(id))
  623. return;
  624. var button = defaultToolbarButtons[id];
  625. if (button.sideContainerId
  626. && button.sideContainerId === containerId) {
  627. UIUtil.buttonClick(button.id, "selected");
  628. return;
  629. }
  630. }
  631. );
  632. },
  633. /**
  634. * Handles full screen toggled.
  635. *
  636. * @param {boolean} isFullScreen indicates if we're currently in full
  637. * screen mode
  638. */
  639. _handleFullScreenToggled(isFullScreen) {
  640. let element
  641. = document.getElementById("toolbar_button_fullScreen");
  642. element.className = isFullScreen
  643. ? element.className
  644. .replace("icon-full-screen", "icon-exit-full-screen")
  645. : element.className
  646. .replace("icon-exit-full-screen", "icon-full-screen");
  647. Toolbar._setToggledState("toolbar_button_fullScreen", isFullScreen);
  648. },
  649. /**
  650. * Initialise toolbar buttons.
  651. */
  652. _initToolbarButtons() {
  653. interfaceConfig.TOOLBAR_BUTTONS.forEach((value, index) => {
  654. let place = getToolbarButtonPlace(value);
  655. if (value && value in defaultToolbarButtons) {
  656. let button = defaultToolbarButtons[value];
  657. this._addToolbarButton(
  658. button,
  659. place,
  660. (interfaceConfig.MAIN_TOOLBAR_SPLITTER_INDEX !== undefined
  661. && index
  662. === interfaceConfig.MAIN_TOOLBAR_SPLITTER_INDEX));
  663. }
  664. });
  665. },
  666. /**
  667. * Adds the given button to the main (top) or extended (left) toolbar.
  668. *
  669. * @param {Object} the button to add.
  670. * @param {boolean} isFirst indicates if this is the first button in the
  671. * toolbar
  672. * @param {boolean} isLast indicates if this is the last button in the
  673. * toolbar
  674. * @param {boolean} isSplitter if this button is a splitter button for
  675. * the dialog, which means that a special splitter style will be applied
  676. */
  677. _addToolbarButton(button, place, isSplitter) {
  678. const places = {
  679. main: 'mainToolbar',
  680. extended: 'extendedToolbarButtons'
  681. };
  682. let id = places[place];
  683. let buttonElement = document.createElement("a");
  684. if (button.className) {
  685. buttonElement.className = button.className;
  686. }
  687. if (isSplitter) {
  688. let splitter = document.createElement('span');
  689. splitter.className = 'toolbar__splitter';
  690. document.getElementById(id).appendChild(splitter);
  691. }
  692. buttonElement.id = button.id;
  693. if (button.html)
  694. buttonElement.innerHTML = button.html;
  695. //TODO: remove it after UI.updateDTMFSupport fix
  696. if (button.hidden)
  697. buttonElement.style.display = 'none';
  698. if (button.shortcutAttr)
  699. buttonElement.setAttribute("shortcut", button.shortcutAttr);
  700. if (button.content)
  701. buttonElement.setAttribute("content", button.content);
  702. if (button.i18n)
  703. buttonElement.setAttribute("data-i18n", button.i18n);
  704. buttonElement.setAttribute("data-container", "body");
  705. buttonElement.setAttribute("data-placement", "bottom");
  706. this._addPopups(buttonElement, button.popups);
  707. document.getElementById(id)
  708. .appendChild(buttonElement);
  709. },
  710. _addPopups(buttonElement, popups = []) {
  711. popups.forEach((popup) => {
  712. let popupElement = document.createElement("ul");
  713. popupElement.id = popup.id;
  714. popupElement.className = popup.className;
  715. let liElement = document.createElement("li");
  716. liElement.setAttribute("data-i18n", popup.dataAttr);
  717. popupElement.appendChild(liElement);
  718. buttonElement.appendChild(popupElement);
  719. });
  720. },
  721. /**
  722. * Sets the toggled state of the given element depending on the isToggled
  723. * parameter.
  724. *
  725. * @param elementId the element identifier
  726. * @param isToggled indicates if the element should be toggled or untoggled
  727. */
  728. _setToggledState(elementId, isToggled) {
  729. $("#" + elementId).toggleClass("toggled", isToggled);
  730. },
  731. /**
  732. * Sets Shortcuts and Tooltips for all toolbar buttons
  733. *
  734. * @private
  735. */
  736. _setShortcutsAndTooltips() {
  737. Object.keys(defaultToolbarButtons).forEach(
  738. id => {
  739. if (UIUtil.isButtonEnabled(id)) {
  740. let button = defaultToolbarButtons[id];
  741. let buttonElement = document.getElementById(button.id);
  742. if (!buttonElement) return false;
  743. let tooltipPosition
  744. = (interfaceConfig.MAIN_TOOLBAR_BUTTONS
  745. .indexOf(id) > -1)
  746. ? "bottom" : "right";
  747. UIUtil.setTooltip( buttonElement,
  748. button.tooltipKey,
  749. tooltipPosition);
  750. if (button.shortcut)
  751. APP.keyboardshortcut.registerShortcut(
  752. button.shortcut,
  753. button.shortcutAttr,
  754. button.shortcutFunc,
  755. button.shortcutDescription
  756. );
  757. }
  758. }
  759. );
  760. },
  761. /**
  762. * Sets Handlers for all toolbar buttons
  763. *
  764. * @private
  765. */
  766. _setButtonHandlers() {
  767. Object.keys(buttonHandlers).forEach(
  768. buttonId => $(`#${buttonId}`).click(function(event) {
  769. !$(this).prop('disabled') && buttonHandlers[buttonId](event);
  770. })
  771. );
  772. }
  773. };
  774. export default Toolbar;