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

helpers.js 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // @flow
  2. /**
  3. * A helper function that behaves similar to Object.assign, but only reassigns a
  4. * property in target if it's defined in source.
  5. *
  6. * @param {Object} target - The target object to assign the values into.
  7. * @param {Object} source - The source object.
  8. * @returns {Object}
  9. */
  10. export function assignIfDefined(target: Object, source: Object) {
  11. const to = Object(target);
  12. for (const nextKey in source) {
  13. if (source.hasOwnProperty(nextKey)) {
  14. const value = source[nextKey];
  15. if (typeof value !== 'undefined') {
  16. to[nextKey] = value;
  17. }
  18. }
  19. }
  20. return to;
  21. }
  22. /**
  23. * Tries to copy a given text to the clipboard.
  24. * Returns true if the action succeeds.
  25. *
  26. * @param {string} textToCopy - Text to be copied.
  27. * @returns {boolean}
  28. */
  29. export function copyText(textToCopy: string) {
  30. const fakeTextArea = document.createElement('textarea');
  31. let result;
  32. // $FlowFixMe
  33. document.body.appendChild(fakeTextArea);
  34. fakeTextArea.value = textToCopy;
  35. fakeTextArea.select();
  36. try {
  37. result = document.execCommand('copy');
  38. } catch (err) {
  39. result = false;
  40. }
  41. // $FlowFixMe
  42. document.body.removeChild(fakeTextArea);
  43. return result;
  44. }
  45. /**
  46. * Creates a deferred object.
  47. *
  48. * @returns {{promise, resolve, reject}}
  49. */
  50. export function createDeferred(): Object {
  51. const deferred = {};
  52. deferred.promise = new Promise((resolve, reject) => {
  53. deferred.resolve = resolve;
  54. deferred.reject = reject;
  55. });
  56. return deferred;
  57. }
  58. const MATCH_OPERATOR_REGEXP = /[|\\{}()[\]^$+*?.-]/g;
  59. /**
  60. * Escape RegExp special characters.
  61. *
  62. * Based on https://github.com/sindresorhus/escape-string-regexp.
  63. *
  64. * @param {string} s - The regexp string to escape.
  65. * @returns {string}
  66. */
  67. export function escapeRegexp(s: string) {
  68. if (typeof s !== 'string') {
  69. throw new TypeError('Expected a string');
  70. }
  71. return s.replace(MATCH_OPERATOR_REGEXP, '\\$&');
  72. }
  73. /**
  74. * Returns the base URL of the app.
  75. *
  76. * @param {Object} w - Window object to use instead of the built in one.
  77. * @returns {string}
  78. */
  79. export function getBaseUrl(w: Object = window) {
  80. const doc = w.document;
  81. const base = doc.querySelector('base');
  82. if (base && base.href) {
  83. return base.href;
  84. }
  85. const { protocol, host } = w.location;
  86. return `${protocol}//${host}`;
  87. }
  88. /**
  89. * Returns the namespace for all global variables, functions, etc that we need.
  90. *
  91. * @returns {Object} The namespace.
  92. *
  93. * NOTE: After React-ifying everything this should be the only global.
  94. */
  95. export function getJitsiMeetGlobalNS() {
  96. if (!window.JitsiMeetJS) {
  97. window.JitsiMeetJS = {};
  98. }
  99. if (!window.JitsiMeetJS.app) {
  100. window.JitsiMeetJS.app = {};
  101. }
  102. return window.JitsiMeetJS.app;
  103. }
  104. /**
  105. * Prints the error and reports it to the global error handler.
  106. *
  107. * @param {Error} e - The error object.
  108. * @param {string} msg - A custom message to print in addition to the error.
  109. * @returns {void}
  110. */
  111. export function reportError(e: Object, msg: string = '') {
  112. console.error(msg, e);
  113. window.onerror && window.onerror(msg, null, null, null, e);
  114. }